《spring源码深度解析》第五章bean的加载

1.先分析一段spring中加载bean的一个方法.

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
     //根据入参name获取对应的beanName String beanName
= this.transformedBeanName(name);
     
     //目的:1. 检查缓存中或者实例工厂中是否已经加载该bean
     //创建单例bean的时候会存在依赖注入的情况,为避免循环依赖,spring创建bean的原则是不等bean创建完成就将创建bean的objectFactory提早曝光并加入缓存中
     //当创建当前bean需要依赖上个bean的时候,直接使用objectFactory
     //直接尝试从缓存或者singletonFactories中的ObjectFactory中获取bean
     Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        //目标bean已创建
     if(sharedInstance != null && args == null) { if(this.logger.isTraceEnabled()) {
          //判断bean是否为单例,输出相应log
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 + "\'"); } }        //返回对应的实例,有时候存在如:BeanFactory的情况下,并不返回实例本身而是返回指定某一方法返回的实例 bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); } else {
       //只有在单例的情况下才会尝试解决循环依赖,原型(prototype)模式的情况下,若存在循环依赖,直接抛出异常
if(this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }        //获取parentBeanFactory BeanFactory ex = this.getParentBeanFactory(); if(ex != null && !this.containsBeanDefinition(beanName)) { //若factory不为空且在已加载的bean缓存中(beanDefinationMap)不存在该beanName,尝试parentBeanFactory中寻找
          String var28
= this.originalBeanName(name); if(ex instanceof AbstractBeanFactory) {
            //递归循环在beanFactory中寻找
return ((AbstractBeanFactory)ex).doGetBean(var28, requiredType, args, typeCheckOnly); }            if(args != null) { return ex.getBean(var28, args); } if(requiredType != null) { return ex.getBean(var28, requiredType); } return ex.getBean(var28); }        //如果不只是做类型检查,此处做个标记进行记录 if(!typeCheckOnly) { this.markBeanAsCreated(beanName); } try {
         //将存储XML配置文件的GenericBeanDefination转换为RootBeanDefination,若当前beanName存在父类的情况,则合并父类的相关属性 RootBeanDefinition ex1
= this.getMergedLocalBeanDefinition(beanName); this.checkMergedBeanDefinition(ex1, beanName, args); String[] dependsOn = ex1.getDependsOn(); String[] scopeName;
          //若存在依赖,则递归实例化依赖的bean
if(dependsOn != null) { scopeName = dependsOn; int scope = dependsOn.length; for(int ex2 = 0; ex2 < scope; ++ex2) { String dep = scopeName[ex2]; if(this.isDependent(beanName, dep)) { throw new BeanCreationException(ex1.getResourceDescription(), beanName, "Circular depends-on relationship between \'" + beanName + "\' and \'" + dep + "\'"); }               //缓存依赖调用 this.registerDependentBean(dep, beanName); try { this.getBean(dep); } catch (NoSuchBeanDefinitionException var24) { throw new BeanCreationException(ex1.getResourceDescription(), beanName, "\'" + beanName + "\' depends on missing bean \'" + dep + "\'", var24); } } }           //实例化依赖bean后便可以实例化mbd本身了&单例模式创建 if(ex1.isSingleton()) { sharedInstance = this.getSingleton(beanName, () -> { try { return this.createBean(beanName, ex1, args); } catch (BeansException var5) { this.destroySingleton(beanName); throw var5; } }); bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, ex1); } else if(ex1.isPrototype()) {
            //多例(prototype)模式下创建 scopeName
= null; Object var29; try { this.beforePrototypeCreation(beanName); var29 = this.createBean(beanName, ex1, args); } finally { this.afterPrototypeCreation(beanName); } bean = this.getObjectForBeanInstance(var29, name, beanName, ex1); } else {
            //既不是单例又不是多例的情况下,先获取当前bean的作用域 String var30
= ex1.getScope();
            //若不是已规定的原型类型,则直接抛出异常 Scope var31
= (Scope)this.scopes.get(var30); if(var31 == null) { throw new IllegalStateException("No Scope registered for scope name \'" + var30 + "\'"); } try { Object var32 = var31.get(beanName, () -> { this.beforePrototypeCreation(beanName); Object var4; try { var4 = this.createBean(beanName, ex1, args); } finally { this.afterPrototypeCreation(beanName); } return var4; }); bean = this.getObjectForBeanInstance(var32, name, beanName, ex1); } catch (IllegalStateException var23) { throw new BeanCreationException(beanName, "Scope \'" + var30 + "\' 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; } }      //类型转换 if(requiredType != null && !requiredType.isInstance(bean)) { try { Object var27 = this.getTypeConverter().convertIfNecessary(bean, requiredType); if(var27 == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } else { return var27; } } 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; } }

通过阅读上面代码,对于bean的加载过程中所涉及的步骤大致分下面几步:

1. 转换对应的beanName: a. 入参的beanName可能是别名而不是类名 b.可能是beanFactory.所以需要加以解析

    解析内容包括:

    a. 去除beanFactory的修饰符,即如果入参name="&aa",则去掉修饰符&,使得name=aa

              b. 取指定的alias所表示的beanName.即bean的本名而非别名

2. 尝试从缓存中加载单例: 单例bean在spring中只会创建一次,后续再创建,直接从单例缓存中获取 . 若加载不成功,则再次尝试从singletonFactories中加载.

3. bean的实例化: 若从缓存中得到的bean是原始状态.则需要对bean进行实例化.

   注:缓存中读取到的bean只是最原始的bean.并不一定是最终想要的. 例如实际项目中需对目标bean进行处理. 那就需要经过其他的方法处理后再次获得理想的实例bean . 

4. 原型模式的依赖检查: 只有单例的情况下才会尝试解决循环依赖 . 因为单例模式下,一个容器中bean只会加载及实例化一次 . 当遇到循环依赖时 , 如A依赖B , 当实例化A时,先去加载B , 再实例化A.当加载

5. 检测parentFactory: 如果当前缓存中没有目标bean的话,就会去父类工厂中加载. 

6.将存储XML的GenericBeanDefinition转换为RootBeanDefinition. 从XML中读取到的bean的信息都是存储在GenericBeanDefinition中的 , 而后续针对bean的所有的处理都是针对RootBeanDefinition的,所以加以转换 . 同时也合并父类bean的属性

7.寻找依赖bean

8. 针对不同的scope进行创建bean

9. 类型转换.将返回的bean转换成方法指定的requiretype.: 返回的bean其实是一个string,这里需转换为我们所需要的目标类型 . 

注 : 缓存集合类 . 可翻看AbstractBeanFactory/DefaultSingletonBeanRegistry等源码中.

  常见的一些集合类如 :  singletonObjects[Map]:用于保存beanName和创建bean的实例之间的关系

            singletonFactories[Map]:用于保存 BeanName和创建 bean的 factory之间的关系

            registeredSingletons : 用来保存当前所有已注册的 bean 

            earlySingletonObjects[Map]: 也是保存beanName和 创建bean的factory之间的关系的 , 于singletonFactories区别是, 存储的是循环依赖的时候创建的bean .当单例bean放到里面后,              在bean的创建过程中,就可以通过getBean()获取到实例了 . 在bean加载完成后,即bean的实例加入singletonFactories中后 , 将从  earlySingletonObjects中移除 . 

代码可参考 : 

 1 public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
 2         Assert.notNull(beanName, "Bean name must not be null");
 3         Assert.notNull(singletonObject, "Singleton object must not be null");
 4         Map var3 = this.singletonObjects;
 5         synchronized(this.singletonObjects) {
 6             Object oldObject = this.singletonObjects.get(beanName);
 7             if(oldObject != null) {
 8                 throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name \'" + beanName + "\': there is already object [" + oldObject + "] bound");
 9             } else {
10                 this.addSingleton(beanName, singletonObject);
11             }
12         }
13     }
14 
15     protected void addSingleton(String beanName, Object singletonObject) {
16         Map var3 = this.singletonObjects;
17         synchronized(this.singletonObjects) {
18             this.singletonObjects.put(beanName, singletonObject);
19             this.singletonFactories.remove(beanName);
20             this.earlySingletonObjects.remove(beanName);
21             this.registeredSingletons.add(beanName);
22         }
23     }
24 
25     protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
26         Assert.notNull(singletonFactory, "Singleton factory must not be null");
27         Map var3 = this.singletonObjects;
28         synchronized(this.singletonObjects) {
29             if(!this.singletonObjects.containsKey(beanName)) {
30                 this.singletonFactories.put(beanName, singletonFactory);
31                 this.earlySingletonObjects.remove(beanName);
32                 this.registeredSingletons.add(beanName);
33             }
34 
35         }
36     }

             singletonsCurrentlyInCreation[Set]:用于加载实例前记录加载状态. 

循环依赖 : 即A中依赖B . B中依赖A .

  spring容器的循环依赖包括构造器循环依赖和setter循环依赖 .

    构造器循环依赖 : 是无法解决的 . 遇到这种情况 , 只能抛出BeanCurrentlyInCreationException异常表示循环依赖 . 

    setter循环依赖 : 是通过spring容器提前暴露刚完成构造器注入但未完成其他步骤的bean来完成的 . 

  spring解决循环依赖的方案 : 只能解决单例模式下的setter循环依赖 . 

    提前暴露一个工厂方法 . 从而使得其他bean能从earlySingletonObjects缓存中引用到该bean . 完成bean的实例化 . 

prototype范围的依赖处理: spring无法完成 . 因为spring容器本身不缓存该作用域的bean . 因此无法像单例bean那样提前暴露一个创建中的bean 

posted @ 2020-11-24 00:35  每天学习1点点  阅读(46)  评论(0)    收藏  举报