AbstractBeanFactory 实现了依赖关系处理,它 继承了 DefaultSingletonBeanRegistry 类,并进一步丰富了已有的功能,这个类提供了 singleton/prototype 的选择,单例 cache,对于 FactoryBean 的处理,bean 定义的处理以及 bean 的销毁等。
其中比较重要的功能是对 BeanFactory 中 getBean 方法的实现。
public Object getBean(String name) throws BeansException { return this.doGetBean(name, (Class)null, (Object[])null, false); } public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return this.doGetBean(name, requiredType, (Object[])null, false); } public Object getBean(String name, Object... args) throws BeansException { return this.doGetBean(name, (Class)null, args, false); } public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException { return this.doGetBean(name, requiredType, args, false); } 复制代码
内部调用 doGetBean()
方法,这个方法的代码比较长,各位耐心看下:
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 获取 beanName,这里是一个转换动作,将 name 转换Wie beanName String beanName = this.transformedBeanName(name); /* *检查缓存中的实例工程是否存在对应的实例 *为何要优先使用这段代码呢? *因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖 *spring创建bean的原则是在不等bean创建完就会将创建bean的objectFactory提前曝光,即将其加入到缓存中,一旦下个bean创建时依赖上个bean则直接使用objectFactory *直接从缓存中或singletonFactories中获取objectFactory *就算没有循环依赖,只是单纯的依赖注入,如B依赖A,如果A已经初始化完成,B进行初始化时,需要递归调用getBean获取A,这是A已经在缓存里了,直接可以从这里取到 */ Object sharedInstance = this.getSingleton(beanName); Object bean; if (sharedInstance != null && args == null) { if (this.logger.isTraceEnabled()) { if (this.isSingletonCurrentlyInCreation(beanName)) { this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } //返回对应的实例,有些时候并不是直接返回实例,而是返回某些方法返回的实例 //这里涉及到我们上面讲的FactoryBean,如果此Bean是FactoryBean的实现类,如果name前缀为"&",则直接返回此实现类的bean,如果没有前缀"&",则需要调用此实现类的getObject方法,返回getObject里面真是的返回对象 bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); } else { //只有在单例的情况下才会解决循环依赖 if (this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //尝试从parentBeanFactory中查找bean BeanFactory parentBeanFactory = this.getParentBeanFactory(); if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) { String nameToLookup = this.originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); } if (args != null) { return parentBeanFactory.getBean(nameToLookup, args); } if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } return parentBeanFactory.getBean(nameToLookup); } //如果不是仅仅做类型检查,则这里需要创建bean,并做记录 if (!typeCheckOnly) { this.markBeanAsCreated(beanName); } try { //将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,同时如果存在父bean的话则合并父bean的相关属性 RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); // 检查给定的合并的 BeanDefinition this.checkMergedBeanDefinition(mbd, beanName, args); //如果存在依赖则需要递归实例化依赖的bean String[] dependsOn = mbd.getDependsOn(); String[] var11; if (dependsOn != null) { var11 = dependsOn; int var12 = dependsOn.length; for(int var13 = 0; var13 < var12; ++var13) { String dep = var11[var13]; // 若给定的依赖 bean 已经注册为依赖给定的b ean // 循环依赖的情况 if (this.isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 缓存依赖调用 this.registerDependentBean(dep, beanName); try { this.getBean(dep); } catch (NoSuchBeanDefinitionException var24) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24); } } } // 单例模式 // 实例化依赖的bean后对bean本身进行实例化 if (mbd.isSingleton()) { sharedInstance = this.getSingleton(beanName, () -> { try { return this.createBean(beanName, mbd, args); } catch (BeansException var5) { // 显示从单利缓存中删除 bean 实例 // 因为单例模式下为了解决循环依赖,可能它已经存在了,所以销毁它 this.destroySingleton(beanName); throw var5; } }); bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) {// 原型模式 var11 = null; Object prototypeInstance; try { this.beforePrototypeCreation(beanName); prototypeInstance = this.createBean(beanName, mbd, args); } finally { this.afterPrototypeCreation(beanName); } bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else {// 从指定的 scope 下创建 bean String scopeName = mbd.getScope(); Scope 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, () -> { this.beforePrototypeCreation(beanName); Object var4; try { var4 = this.createBean(beanName, mbd, args); } finally { this.afterPrototypeCreation(beanName); } return var4; }); bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException var23) { 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", var23); } } } catch (BeansException var26) { this.cleanupAfterBeanCreationFailure(beanName); throw var26; } } // 检查需要的类型是否符合 bean 的实际类型 if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } else { return convertedBean; } } catch (TypeMismatchException var25) { if (this.logger.isTraceEnabled()) { this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } else { return bean; } } 复制代码
代码是相当长,处理逻辑也是相当复杂,下面将其进行拆分讲解。
获取 beanName
String beanName = this.transformedBeanName(name); 复制代码
这里传递的是 name,不一定是 beanName,可能是 aliasName,也有可能是 FactoryBean(带“&”前缀),所以这里需要调用 transformedBeanName()
方法对 name 进行一番转换。
AbstractBeanFactory 类中的 transformedBeanName()方法:
protected String transformedBeanName(String name) { return this.canonicalName(BeanFactoryUtils.transformedBeanName(name)); } 复制代码
BeanFactoryUtils 类中的 transformedBeanName()方法:
// 去除 FactoryBean 的修饰符 public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); return !name.startsWith("&") ? name : (String)transformedBeanNameCache.computeIfAbsent(name, (beanName) -> { do { beanName = beanName.substring("&".length()); } while(beanName.startsWith("&")); return beanName; }); } 复制代码
SimpleAliasRegistry 类中的 canonicalName()方法:
// 转换 aliasName public String canonicalName(String name) { String canonicalName = name; String resolvedName; do { resolvedName = (String)this.aliasMap.get(canonicalName); if (resolvedName != null) { canonicalName = resolvedName; } } while(resolvedName != null); return canonicalName; } 复制代码
主要处理过程包括两步:
- 去除 FactoryBean 的修饰符。如果 name 以 “&” 为前缀,那么会去掉该 “&”,例如,
name = "&studentService"
,则会是name = "studentService"
。 - 取指定的 alias 所表示的最终 beanName。主要是一个循环获取 beanName 的过程,例如别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。
缓存中获取单例bean
单例在 Spring 的同一个容器中只会被创建一次,后续再获取 bean 直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再尝试从 singletonFactorry 加载。因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring 创建 bean 的 时候不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提早加入到缓存中,一旦下一个 bean 创建时需要依赖上个 bean,则直接使用 ObjectFactory;就算没有循环依赖,只是单纯的依赖注入,如果B依赖A,如果A已经完成初始化,B进行初始化时,需要递归调用 getBean 获取A,这时A已经在缓存里了,直接可以从这里取到。接下来我们看下获取单例 bean 的方法 getSingleton(beanName)
,进入方法体:
@Nullable public Object getSingleton(String beanName) { //参数true是允许早期依赖 return this.getSingleton(beanName, true); } @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { //检查缓存中是否存在实例,这里就是上面说的单纯的依赖注入,如B依赖A,如果A已经初始化完成,B进行初始化时,需要递归调用getBean获取A,这是A已经在缓存里了,直接可以从这里取到 Object singletonObject = this.singletonObjects.get(beanName); //如果缓存为空且单例bean正在创建中,则锁定全局变量,为什么要判断bean在创建中呢?这里就是可以判断是否循环依赖了。 //A依赖B,B也依赖A,A实例化的时候,发现依赖B,则递归去实例化B,B发现依赖A,则递归实例化A,此时会走到原点A的实例化,第一次A的实例化还没完成,只不过把实例化的对象加入到缓存中,但是状态还是正在创建中,由此回到原点发现A正在创建中,由此可以判断是循环依赖了 if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) { synchronized(this.singletonObjects) { //如果此bean正在加载,则不处理 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { //当某些方法需要提前初始化的时候会直接调用addSingletonFactory把对应的ObjectFactory初始化策略存储在singletonFactory中 ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); if (singletonFactory != null) { //使用预先设定的getObject方法 singletonObject = singletonFactory.getObject(); //记录在缓存中,注意earlySingletonObjects和singletonFactories是互斥的 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } 复制代码
这里涉及到很多个存储bean的不同map,简单解释下:
- singletonObjects: 用来存放注册的SingletonBean,具体的实现类是ConcurrentHashMap。
- singletonFactories: 存储制造 singleton 的工厂,当 Spring 制造一个 bean 时因为依赖的 bean 还未完成 Spring 的单例制造会将前者包装成一个 ObjectFactory 放入。ObjectFactory 的返回值就是 bean。
- earlySingletonObjects: 是 singletonFactory 制造出来的 singleton 的缓存 ,与 singletonObjects 的不同之处在于,当一个单例 bean 被放到这里面后,那么当bean还在创建过程中,就可以通过 getBean 方法获取到了,其目的是用来检测循环引用。
- registeredSingletons:用来保存当前所有已注册的 bean.
这个方法先尝试从 singletonObjects 里面获取实例,如果如果获取不到再从 earlySingletonObjects 里面获取,如果还获取不到,再尝试从 singletonFactories 里面获取 beanName 对应的 ObjectFactory,然后再调用这个 ObjectFactory 的 getObject 方法创建 bean,并放到 earlySingletonObjects 里面去,并且从 singletonFactoryes 里面 remove 掉这个 ObjectFactory,而对于后续所有的内存操作都只为了循环依赖检测时候使用,即 allowEarlyReference 为 true 的时候才会使用。
从缓存中获取到 bean 以后就要获取实例对象了,这里用到的是 getObjectForBeanInstance 方法。getObjectForBeanInstance 是个频繁使用的方法,无论是从缓存中获得 bean 还是根据不同的 scope 策略加载 bean。总之,我们得到 bean 的实例后,要做的第一步就是调用这个方法来检测一下正确性,其实就是检测获得的 bean 是不是 FactoryBean 类型的 bean,如果是,那么需要调用该 bean 对应的 FactoryBean 实例中的 getObject()作为返回值。接下来我们看下此方法的源码:
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { //如果指定的name是工厂相关的(以&开头的) if (BeanFactoryUtils.isFactoryDereference(name)) { //如果是NullBean则直接返回此bean if (beanInstance instanceof NullBean) { return beanInstance; } else if (!(beanInstance instanceof FactoryBean)) {//如果不是FactoryBean类型,则验证不通过抛出异常 throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); } else { //如果获取的beanInstance是FactoryBean类型,但是是以(以&开头的),也直接返回,此时返回的是FactoryBean的实例 if (mbd != null) { mbd.isFactoryBean = true; } return beanInstance; } } else if (!(beanInstance instanceof FactoryBean)) {//如果获取的beanInstance不是FactoryBean类型,则说明是普通的Bean,可直接返回 return beanInstance; } else { Object object = null; // 若 BeanDefinition 为 null,则从缓存中加载 if (mbd != null) { mbd.isFactoryBean = true; } else { object = this.getCachedObjectForFactoryBean(beanName); } // 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean if (object == null) { FactoryBean<?> factory = (FactoryBean)beanInstance; if (mbd == null && this.containsBeanDefinition(beanName)) { mbd = this.getMergedLocalBeanDefinition(beanName); } boolean synthetic = mbd != null && mbd.isSynthetic(); //到了这里说明获取的beanInstance是FactoryBean类型,但没有以"&"开头,此时就要返回factory内部getObject里面的对象了 object = this.getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; } } 复制代码
该方法功能如下:
- 若 name 为工厂相关的(以 & 开头),当 beanInstance 为 NullBean 类型或者是 FactoryBean 类型则直接返回,如果 beanInstance 不为 FactoryBean 类型则抛出 BeanIsNotAFactoryException 异常。这里主要是校验 beanInstance 的正确性。
- 如果 beanInstance 不为 FactoryBean 类型,则直接返回。这里主要是对非 FactoryBean 类型处理。
- 如果 BeanDefinition 为空,则从 factoryBeanObjectCache 中加载,如果还是空,则可以断定 beanInstance 一定是 FactoryBean 类型,则委托
getObjectFromFactoryBean()
方法处理
接着我们来看看真正的核心功能 FactoryBeanRegistrySupport 类中的 getObjectFromFactoryBean(factory, beanName, !synthetic)方法中实现的,继续跟进代码:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { // 为单例模式且singletonObjects缓存中存在 if (factory.isSingleton() && this.containsSingleton(beanName)) { synchronized(this.getSingletonMutex()) { // 从缓存中获取指定的 factoryBean Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { // 为空,则从 FactoryBean 中获取对象 object = this.doGetObjectFromFactoryBean(factory, beanName); // 再从缓存中获取,不知出于什么考虑,不是已经加锁了吗 Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // 需要后续处理 if (shouldPostProcess) { // 若该 bean 处于创建中,则返回非处理对象,而不是存储它 if (this.isSingletonCurrentlyInCreation(beanName)) { return object; } // 前置处理 this.beforeSingletonCreation(beanName); try { // 对从 FactoryBean 获取的对象进行后处理 // 生成的对象将暴露给bean引用 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); } } if (this.containsSingleton(beanName)) { 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; } } 复制代码
主要流程如下:
- 若为单例且单例 bean 缓存中存在 beanName,则继续往下处理(跳转到下一步),否则进入 else 语句从 FactoryBean 中获取 bean 实例对象,如果接受后置处理,则调用
postProcessObjectFromFactoryBean()
进行后置处理。 - 若为单例且单例 bean 缓存中存在 beanName,首先获取锁(代码中多处使用到同步锁,锁的对象都是 this.singletonObjects,主要是因为在单例模式中必须保证全局唯一),然后从 factoryBeanObjectCache 缓存中获取实例对象 object,若 object 为空,则调用
doGetObjectFromFactoryBean()
方法从 FactoryBean 获取对象,其实内部就是调用FactoryBean.getObject()
。 - 如果需要后续处理,则进行进一步处理,步骤如下:
- 若该 bean 处于创建中(isSingletonCurrentlyInCreation),则返回刚才获取的对象
- 调用
beforeSingletonCreation()
进行创建之前的处理。默认实现将该 bean 标志为当前创建的。 - 调用
postProcessObjectFromFactoryBean()
对从 FactoryBean 获取的 bean 实例对象进行后置处理,默认实现是按照原样直接返回,二次实现是在 AbstractAutowireCapableBeanFactory 中实现的,当然子类也可以重写它,比如应用后置处理。 - 调用
afterSingletonCreation()
进行创建 bean 之后的处理,默认实现是将该 bean 标记为不再在创建中。 - 最后加入到 factoryBeanObjectCache 缓存中。
注意: beforeSingletonCreation()
、 afterSingletonCreation()
方法非常重要,因为它们记录着 bean 的加载状态,是检测当前 bean 是否处于创建中的关键之处,对解决 bean 循环依赖起着关键作用。但是需要注意的是,起作用并非是在这里,当执行 getSingleton(beanName, singletonFactory)
方法时,其中使用到上面两个方法,对解决 bean 循环依赖至关重要,关于循环依赖的问题可以翻看上一章节内容。
postProcessObjectFromFactoryBean()
是对从 FactoryBean 处获取的 bean 实例对象进行后置处理,其默认实现是直接返回 object 对象,不做任何处理,子类可以重写,例如应用后处理器。AbstractAutowireCapableBeanFactory 对其提供了实现,如下:
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) { return applyBeanPostProcessorsAfterInitialization(object, beanName); } public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } 复制代码
关于后置处理器,我们之前的文章有讲解过,只需要记住一点:尽可能保证所有 bean 初始化后都会调用注册的 BeanPostProcessor.postProcessAfterInitialization()
方法进行处理 ,在实际开发过程可以针对此特性涉及自己的业务逻辑。
在该方法中最为核心的方法是 doGetObjectFromFactoryBean。
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; } 复制代码
在调试过程中发现,如果 bean 声明为 FactoryBean 类型,则当提取bean时候提取的不是 FactoryBean,而是 FactoryBean 中对应的 getObject 方法返回的 bean,而 doGetObjectFromFactroyBean 正是实现这个功能。
在上面代码中还有一个非常重要的检测方法 isSingletonCurrentlyInCreation(beanName)
,该方法用于判断该 beanName 对应的 bean 是否在创建过程中,注意这个过程讲的是整个工厂中。如下:
public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); } 复制代码
原型模式依赖检查与 parentBeanFactory
if (this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = this.getParentBeanFactory(); if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) { String nameToLookup = this.originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); } if (args != null) { return parentBeanFactory.getBean(nameToLookup, args); } if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } return parentBeanFactory.getBean(nameToLookup); } 复制代码
主要流程为:
- 检测。若当前 bean 在创建,则抛出 BeanCurrentlyInCreationException 异常。
- 如果 beanDefinitionMap 中不存在 beanName 的 BeanDefinition(即在 Spring bean 初始化过程中没有加载)且 parentBeanFactory 不为空,则尝试从 parentBeanFactory 中加载。
重点在于第二步,如果满足条件,首先执行 originalBeanName(name)
,其定义如下:
protected String originalBeanName(String name) { String beanName = this.transformedBeanName(name); if (name.startsWith("&")) { beanName = "&" + beanName; } return beanName; } 复制代码
transformedBeanName()
是对 name 进行转换,获取真正的 beanName,因为我们传递的可能是 aliasName,如果 name 是以 “&” 开头的,则加上 “&”,因为在 transformedBeanName()
将 “&” 去掉了,这里补上。
之后的就是继续调用 doGetBean()方法。
类型检查与依赖处理
if (!typeCheckOnly) { this.markBeanAsCreated(beanName); } protected void markBeanAsCreated(String beanName) { if (!this.alreadyCreated.contains(beanName)) { // 加上全局锁 synchronized(this.mergedBeanDefinitions) { if (!this.alreadyCreated.contains(beanName)) { this.clearMergedBeanDefinition(beanName); // 添加到已创建bean 集合中 this.alreadyCreated.add(beanName); } } } } 复制代码
参数 typeCheckOnly 是用来判断调用 getBean()
是否为类型检查而不是获取 bean,默认值为 false,即不是做类型检查而是创建 bean。
获取 RootBeanDefinition
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); this.checkMergedBeanDefinition(mbd, beanName, args); 复制代码
调用 getMergedLocalBeanDefinition()
获取相对应的 BeanDefinition,如下:
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { RootBeanDefinition mbd = (RootBeanDefinition)this.mergedBeanDefinitions.get(beanName); return mbd != null && !mbd.stale ? mbd : this.getMergedBeanDefinition(beanName, this.getBeanDefinition(beanName)); } 复制代码
首先直接从 mergedBeanDefinitions 缓存中获取相应的 RootBeanDefinition,如果存在则直接返回否则调用 getMergedBeanDefinition()
获取 RootBeanDefinition,若获取的 BeanDefinition 为子 BeanDefinition,则需要合并父类的相关属性。关于 BeanDefinition 的知识,后续我们会专门做讲解。
如果一个 bean 有依赖 bean 的话,那么在初始化该 bean 时是需要先初始化它所依赖的 bean。
// 在初始化 bean 时解析 depends-on 标签时设置 String[] dependsOn = mbd.getDependsOn(); String[] var11; if (dependsOn != null) { var11 = dependsOn; int var12 = dependsOn.length; // 迭代依赖 for(int var13 = 0; var13 < var12; ++var13) { String dep = var11[var13]; // 检验依赖的bean 是否已经注册给当前 bean 获取其他传递依赖bean if (this.isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 注册到依赖bean中 this.registerDependentBean(dep, beanName); try { // 调用 getBean 初始化依赖bean this.getBean(dep); } catch (NoSuchBeanDefinitionException var24) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24); } } } 复制代码
通过迭代的方式依次对依赖 bean 进行检测、校验,如果通过则调用 registerDependentBean(dep, beanName)
方法将两个 bean 之间的依赖关系存起来,具体实现在 DefaultSingletonBeanRegistry 类中,关于该方法在上章节中讲述循环依赖时也提及到。 isDependent()
是校验该依赖是否已经注册给当前 bean。
protected boolean isDependent(String beanName, String dependentBeanName) { synchronized(this.dependentBeanMap) { return this.isDependent(beanName, dependentBeanName, (Set)null); } } 复制代码
同步加锁给 dependentBeanMap 对象,然后调用 isDependent()
校验。dependentBeanMap 对象保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) { // alreadySeen 已经检测的依赖 bean if (alreadySeen != null && ((Set)alreadySeen).contains(beanName)) { return false; } else { // 获取原始 beanName String canonicalName = this.canonicalName(beanName); // 获取当前 beanName 的依赖集合 Set<String> dependentBeans = (Set)this.dependentBeanMap.get(canonicalName); // 不存在依赖,返回false if (dependentBeans == null) { return false; } else if (dependentBeans.contains(dependentBeanName)) {// 存在,则证明存在已经注册的依赖 return true; } else { Iterator var6 = dependentBeans.iterator(); String transitiveDependency; do { if (!var6.hasNext()) { return false; } transitiveDependency = (String)var6.next(); if (alreadySeen == null) { alreadySeen = new HashSet(); } ((Set)alreadySeen).add(beanName); } while(!this.isDependent(transitiveDependency, dependentBeanName, (Set)alreadySeen)); return true; } } } 复制代码
如果校验成功,则调用 registerDependentBean()
将该依赖进行注册,便于在销毁 bean 之前对其进行销毁。
public void registerDependentBean(String beanName, String dependentBeanName) { String canonicalName = this.canonicalName(beanName); Set dependenciesForBean; synchronized(this.dependentBeanMap) { dependenciesForBean = (Set)this.dependentBeanMap.computeIfAbsent(canonicalName, (k) -> { return new LinkedHashSet(8); }); if (!dependenciesForBean.add(dependentBeanName)) { return; } } synchronized(this.dependenciesForBeanMap) { dependenciesForBean = (Set)this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, (k) -> { return new LinkedHashSet(8); }); dependenciesForBean.add(canonicalName); } } 复制代码
其实将就是该映射关系保存到两个集合中:dependentBeanMap、dependenciesForBeanMap。
最后调用 getBean()
实例化依赖 bean。这里和讲解 Spring IoC之循环依赖处理时不同,虽然都是递归进去调用 getBean()
方法,讲解循环依赖时是在 BeanDefinitionValueResolver 类中的 resolveReference()
方法内,进而调用 getBean()
方法。