Spring IOC 源码学习4 getBean

1 容器的初始化

1.1 SpringIoc 容器的工作流如下图所示

1.2 实现流程

1.2.1 容器初始化

  • 通过Resource ResourceLoader 加载 Configuration Metadata
  • 解析 Configuration Metadata信息,封装成 BeanDefinition 并注册到 BeanDefinitionRegistry 中

1.2.2 加载bean

  • 通过BeanFactory.getBean() 加载bean
  • 对bean信息进行初始化

2 源码解析

2.1 源码警告

  • 当显示或者隐式地调用 BeanFactory.getBean(String name) 方法时,则会触发加载 Bean 阶段。代码如下:

2.1.1 getBean

// 方法位于AbstractBeanFactory.java

public Object getBean(String name) throws BeansException {

// getBean 是一个空壳方法,所有的逻辑都封装在 doGetBean 方法中

returndoGetBean(name, null, null, false);

}

2.1.2 doGetBean

  • 内部其实调用的doGetBean(Spring 套路都是这样子哈哈,包括事物那里)

    protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)

throws BeansException {

/*

* 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两点原因:

* 1. 如果 name 是 alias ,则获取对应映射的 beanName 。

* 2. 剥离工厂引用前缀&

*/

final String beanName = transformedBeanName(name);

Object bean;

/*

* 从缓存中或者实例工厂中获取 Bean 对象

* 从缓存中获取单例 bean。Spring 是使用 Map 作为 beanName 和 bean 实例的缓存的,所以这

* 里暂时可以把 getSingleton(beanName) 等价于 beanMap.get(beanName)。当然,实际的

* 逻辑并非如此简单,后面再细说。

*/

Object sharedInstance = getSingleton(beanName);

/*

* 如果 sharedInstance = null表明这个实例还没创建。

* BeanFactory 只会在调用 getBean 获取 bean 时再实例化,也就是懒加载。

* BeanFactory 不会多次实例化单例 bean。

*/

if (sharedInstance != null && args == null) {

//记录日志 没啥可说的

if (logger.isDebugEnabled()) {

if (isSingletonCurrentlyInCreation(beanName)) {

logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +

"' that is not fully initialized yet - a consequence of a circular reference");

}

else {

logger.debug("Returning cached instance of singleton bean '" + beanName + "'");

}

}

/*

* 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果

* 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果

* sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的bean 实例。

*/

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

}

/*

* sharedInstance 为空,此时 beanName 对应的 bean 实例可能还未创建。也有可能父容器里已经实例化,需要先去父容器查找 这里有些不明白,先标注下然后后续查看

*/

else {

// BeanFactory 不缓存 Prototype 类型的 bean ,Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常

if (isPrototypeCurrentlyInCreation(beanName)) {

throw new BeanCurrentlyInCreationException(beanName);

}

// 如果 sharedInstance = null,则到父容器中查找 bean 实例 getParentBeanFactory 后续在研究

BeanFactory parentBeanFactory = getParentBeanFactory();

//containsBeanDefinition 方法实际就是判断 org.springframework.beans.factory.support.DefaultListableBeanFactory#beanDefinitionMap 是否有key beanName

if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {

// 获取 name 对应的 beanName,如果 name 是以 & 字符开头,则返回 & + beanName

String nameToLookup = originalBeanName(name);

// 根据 args 是否为空,以决定调用父容器哪个方法获取 bean

if (args != null) {

return (T) parentBeanFactory.getBean(nameToLookup, args);

}

else {

return parentBeanFactory.getBean(nameToLookup, requiredType);

}

}

if (!typeCheckOnly) {

markBeanAsCreated(beanName);

}

try {

// 合并父 BeanDefinition 与子 BeanDefinition,后面会单独分析这个方法

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

checkMergedBeanDefinition(mbd, beanName, args);

// 检查是否有 dependsOn 依赖,如果有则先初始化所依赖的 bean

String[] dependsOn = mbd.getDependsOn();

if (dependsOn != null) {

for (String dep : dependsOn) {

/*

* 检测是否存在 depends-on 循环依赖,若存在则抛异常。比如 A 依赖 B,

* B 又依赖 A,他们的配置如下:

* <bean id="beanA" class="BeanA" depends-on="beanB">

* <bean id="beanB" class="BeanB" depends-on="beanA">

*

* beanA 要求 beanB 在其之前被创建,但 beanB 又要求 beanA 先于它

* 创建。这个时候形成了循环,对于 depends-on 循环,Spring 会直接

* 抛出异常

*/

if (isDependent(beanName, dep)) {

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");

}

// 注册依赖记录

registerDependentBean(dep, beanName);

try {

// 加载 depends-on 依赖

getBean(dep);

}

catch (NoSuchBeanDefinitionException ex) {

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

"'" + beanName + "' depends on missing bean '" + dep + "'", ex);

}

}

}

// 创建 bean 实例

if (mbd.isSingleton()) {

/*

* 这里并没有直接调用 createBean 方法创建 bean 实例,而是通过

* getSingleton(String, ObjectFactory) 方法获取 bean 实例。

* getSingleton(String, ObjectFactory) 方法会在内部调用

* ObjectFactory 的 getObject() 方法创建 bean,并会在创建完成后,

* 将 bean 放入缓存中。关于 getSingleton 方法的分析,本文先不展开,我会在

* 后面的文章中进行分析

*/

sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {

@Override

public Object getObject() throws BeansException {

try {

// 创建 bean 实例

return createBean(beanName, mbd, args);

}

catch (BeansException ex) {

destroySingleton(beanName);

throw ex;

}

}

});

// 如果 bean 是 FactoryBean 类型,则调用工厂方法获取真正的 bean 实例。否则直接返回 bean 实例

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

}

// 创建 prototype 类型的 bean 实例

elseif (mbd.isPrototype()) {

Object prototypeInstance = null;

try {

beforePrototypeCreation(beanName);

prototypeInstance = createBean(beanName, mbd, args);

}

finally {

afterPrototypeCreation(beanName);

}

bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

}

// 创建其他类型的 bean 实例

else {

String scopeName = mbd.getScope();

final Scope scope = this.scopes.get(scopeName);

if (scope == null) {

throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");

}

try {

Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {

@Override

public Object getObject() throws BeansException {

beforePrototypeCreation(beanName);

try {

return createBean(beanName, mbd, args);

}

finally {

afterPrototypeCreation(beanName);

}

}

});

bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

}

catch (IllegalStateException ex) {

throw new BeanCreationException(beanName,

"Scope '" + scopeName + "' is not active for the current thread; consider " +

"defining a scoped proxy for this bean if you intend to refer to it from a singleton",

ex);

}

}

}

catch (BeansException ex) {

cleanupAfterBeanCreationFailure(beanName);

throw ex;

}

}

// 如果需要进行类型转换,则在此处进行转换。类型转换这一块我没细看,就不多说了。

if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {

try {

return getTypeConverter().convertIfNecessary(bean, requiredType);

}

catch (TypeMismatchException ex) {

if (logger.isDebugEnabled()) {

logger.debug("Failed to convert bean '" + name + "' to required type '" +

ClassUtils.getQualifiedName(requiredType) + "'", ex);

}

throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());

}

}

// 返回 bean

return (T) bean;

}

主要步骤

  • 转换 beanName
  • 从缓存中获取实例
  • 如果实例不为空,且 args = null。调用 getObjectForBeanInstance 方法,并按 name 规则返回相应的 bean 实例
  • 若上面的条件不成立,则到父容器中查找 beanName 对有的 bean 实例,存在则直接返回
  • 若父容器中不存在,则进行下一步操作 – 合并 BeanDefinition
  • 处理 depends-on 依赖
  • 创建并缓存 bean
  • 调用 getObjectForBeanInstance 方法,并按 name 规则返回相应的 bean 实例
  • 按需转换 bean 类型,并返回转换后的 bean 实例。

2.1.3 transformedBeanName 源码

  • 为什么要 transformedBeanName 呢?Spring 肯定不会做无用功,主要有以下几个原因
  • 处理以字符 & 开头的 name,防止 BeanFactory 无法找到与 name 对应的 bean 实例
  • 处理 别名 通过别名找到最终的beanName

protected String transformedBeanName(String name) {

return canonicalName(BeanFactoryUtils.transformedBeanName(name));

}

2.1.4 BeanFactoryUtils.transformedBeanName

  • 逻辑很简单就是去除入参中的 &

/**

* beanName 的缓存

*/

private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();

/**

* 去除 FactoryBean 的修饰符 & 如果 name 以 “&” 为前缀,那么会去掉该 "&"

* 例如,name = "&HelloService" ,则会是 name = "HelloService"

*/

public static String transformedBeanName(String name) {

Assert.notNull(name, "'name' must not be null");

if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { // BeanFactory.FACTORY_BEAN_PREFIX = &

return name;

}

// computeIfAbsent 方法,分成两种情况:

// 1. 未存在,则进行计算执行,并将结果添加到缓存、

// 2. 已存在,则直接返回,无需计算。

return transformedBeanNameCache.computeIfAbsent(name, beanName -> {

do {

beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());

//BeanFactory.FACTORY_BEAN_PREFIX = "&"

} while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));

return beanName;

});

}

2.1.5 SimpleAliasRegistry.canonicalName

  • 从aliasMap 获取最终的beanName, 采用了循环主要是考虑到多层别名

   <bean id="hello" class="service.Hello"/>

<alias name="hello"alias="aliasA"/>

<alias name="aliasA"alias="aliasB"/>

  • 上面的别名指向关系为 aliasB -> aliasA -> hello,对于上面的别名配置
  • aliasMap 中数据视图为:aliasMap = [<aliasB, aliasA>, <aliasA, hello>]。通过下面的循环解析别名

    aliasB 最终指向的 beanName

// alias -> beanName 的缓存

private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

public String canonicalName(String name) {

String canonicalName = name;

String resolvedName;

/*

* 循环,从 aliasMap 中,获取到最终的 beanName

*/

do {

resolvedName = this.aliasMap.get(canonicalName);

if (resolvedName != null) {

canonicalName = resolvedName;

}

}

while (resolvedName != null);

return canonicalName;

}

2.1.6 getSingleton(String beanName)

  • 代码位于 /org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

/**  singleton 缓存map  格式为 bean name --> bean instance */

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** singleton factory 缓存 map, 格式为 bean name --> ObjectFactory */

private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

/** Cache of early singleton objects: bean name --> bean instance */

private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

/** Set of registered singletons, containing the bean names in registration order */

private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);

/** 创建中的bean */

private final Set<String> singletonsCurrentlyInCreation =

Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

/** Names of beans currently excluded from in creation checks */

private final Set<String> inCreationCheckExclusions =

Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

public Object getSingleton(String beanName) {

return getSingleton(beanName, true);

}

/**

* allowEarlyReference 表示是否允许其他 bean 引用

*/

protected Object getSingleton(String beanName, boolean allowEarlyReference) {

// 从 singletonObjects 获取实例,singletonObjects 中缓存的实例都是完全实例化好的 bean,可以直接使用

Object singletonObject = this.singletonObjects.get(beanName);

/*

* 如果 singletonObject = null,表明还没创建,或者还没完全创建好。

*/

if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

synchronized (this.singletonObjects) {

// 从 earlySingletonObjects 中获取提前曝光的 bean,用于处理循环引用

singletonObject = this.earlySingletonObjects.get(beanName);

// 如果如果 singletonObject = null,且允许提前曝光 bean 实例,则从相应的 ObjectFactory 获取一个原始的(raw)bean(尚未填充属性)

if (singletonObject == null && allowEarlyReference) {

// 获取相应的工厂类

ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);

if (singletonFactory != null) {

// 提前曝光 bean 实例,用于解决循环依赖

singletonObject = singletonFactory.getObject();

// 放入缓存中,如果还有其他 bean 依赖当前 bean,其他 bean 可以直接从 earlySingletonObjects 取结果

this.earlySingletonObjects.put(beanName, singletonObject);

//移除bean factory 因为已经出事花了一个原始bean放入 earlySingletonObjects

this.singletonFactories.remove(beanName);

}

}

}

}

return (singletonObject != NULL_OBJECT ? singletonObject : null);

}

2.1.7 判断bean是否创建中

public boolean isSingletonCurrentlyInCreation(String beanName) {

return this.singletonsCurrentlyInCreation.contains(beanName);

}

2.1.8 AbstractBeanFactory.getObjectForBeanInstance

  • 从FactoryBean 获取bean 实例

protected Object getObjectForBeanInstance(

Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

// 如果 name 以 & 开头,但 beanInstance 却不是 FactoryBean,抛出异常

if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {

throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());

}

/**

* 1 beanInstance 是 FactoryBean 需要调用 工厂方法生成bean

* 2 beanInstance 是一个普通bean 直接返回

*/

if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {

return beanInstance;

}

Object object = null;

if (mbd == null) {

//如果 mbd 为空,则从缓存中加载 bean。FactoryBean 生成的单例 bean 会被缓存 在 factoryBeanObjectCache 集合中,不用每次都创建

object = getCachedObjectForFactoryBean(beanName);

}

if (object == null) {

// 到这一步肯定是FactoryBean

FactoryBean<?> factory = (FactoryBean<?>) beanInstance;

// 如果mbd is null 则判断是否存在 beanname 的 BeanDefinition,若存在 合并

if (mbd == null && containsBeanDefinition(beanName)) {

mbd = getMergedLocalBeanDefinition(beanName);

}

boolean synthetic = (mbd != null && mbd.isSynthetic());

object = getObjectFromFactoryBean(factory, beanName, !synthetic);

}

return object;

}

2.1.9 org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean

/**

* FactoryBean 也有单例和原型之分

* 针对单例FactoryBean 生成bean 也默认是单例模式,需要放入缓存

* 非单例的FactoryBean 生成的bean 则不会放入缓存

* @param factory

* @param beanName

* @param shouldPostProcess 对bean 进行后置处理

* @return

*/

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {

//如果factory 是单例模式

if (factory.isSingleton() && this.containsSingleton(beanName)) {

synchronized(this.getSingletonMutex()) {

//缓存中获取bean

Object object = this.factoryBeanObjectCache.get(beanName);

if (object == null) {

//使用工厂方法创建bean

object = this.doGetObjectFromFactoryBean(factory, beanName);

Object alreadyThere = this.factoryBeanObjectCache.get(beanName);

if (alreadyThere != null) {

object = alreadyThere;

} else {

if (shouldPostProcess) {

// singletonsCurrentlyInCreation 是否已有该bean Name, 如果有直接返回

if (this.isSingletonCurrentlyInCreation(beanName)) {

return object;

}

this.beforeSingletonCreation(beanName);

try {

//后置处理

object = this.postProcessObjectFromFactoryBean(object, beanName);

} catch (Throwable var14) {

throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var14);

} finally {

this.afterSingletonCreation(beanName);

}

}

// singletonObjects map 是否包含 beanName

if (this.containsSingleton(beanName)) {

//如果包含则 把 FactoryBean 创建的bean 缓存到 factoryBeanObjectCache

//factoryBeanObjectCache 定义于 org.springframework.beans.factory.support.FactoryBeanRegistrySupport

this.factoryBeanObjectCache.put(beanName, object);

}

}

}

return object;

}

} else {

//非单例模式 直接通过工厂方法获取

Object object = this.doGetObjectFromFactoryBean(factory, beanName);

if (shouldPostProcess) {

try {

object = this.postProcessObjectFromFactoryBean(object, beanName);

} catch (Throwable var17) {

throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var17);

}

}

return object;

}

}

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {

Object object;

try {

//这块没太懂

if (System.getSecurityManager() != null) {

AccessControlContext acc = this.getAccessControlContext();

try {

object = AccessController.doPrivileged(factory::getObject, acc);

} catch (PrivilegedActionException var6) {

throw var6.getException();

}

} else {

//直接通过工厂方法获取

object = factory.getObject();

}

} catch (FactoryBeanNotInitializedException var7) {

throw new BeanCurrentlyInCreationException(beanName, var7.toString());

} catch (Throwable var8) {

throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);

}

if (object == null) {

if (this.isSingletonCurrentlyInCreation(beanName)) {

throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");

}

object = new NullBean();

}

return object;

}

待完善中

以上是 Spring IOC 源码学习4 getBean 的全部内容, 来源链接: utcz.com/a/29876.html

回到顶部