zoukankan      html  css  js  c++  java
  • 【spring源码分析】IOC容器初始化(七)

    前言:在【spring源码分析】IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数

    FactoryBeanRegistrySupport#getObjectFromFactoryBean并未进行详细分析,本文将继续对bean加载过程的分析。


    FactoryBeanRegistrySupport#getObjectFromFactoryBean

     1 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
     2         // 为单例模式,其缓存中存在该bean实例
     3         if (factory.isSingleton() && containsSingleton(beanName)) {
     4             /**
     5              * 做同步,内部其实使用的就是{@link DefaultSingletonBeanRegistry#singletonObjects}
     6              */
     7             synchronized (getSingletonMutex()) {
     8                 // 从缓存中获取指定的factoryBean
     9                 Object object = this.factoryBeanObjectCache.get(beanName);
    10                 if (object == null) {
    11                     // 为空,则从FactoryBean中获取对象
    12                     object = doGetObjectFromFactoryBean(factory, beanName);
    13                     // Only post-process and store if not put there already during getObject() call above
    14                     // (e.g. because of circular reference processing triggered by custom getBean calls)
    15                     // 再次从缓存中获取bean对象,主要是因为循环依赖
    16                     Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
    17                     if (alreadyThere != null) {
    18                         object = alreadyThere;
    19                     } else {
    20                         // 需要后续处理
    21                         if (shouldPostProcess) {
    22                             // 如果该Bean处于创建中,则返回处理对象,而不是存储该对象
    23                             if (isSingletonCurrentlyInCreation(beanName)) {
    24                                 // Temporarily return non-post-processed object, not storing it yet..
    25                                 return object;
    26                             }
    27                             // 单例bean的前置处理 用于添加标志,当前bean正处于创建中
    28                             beforeSingletonCreation(beanName);
    29                             try {
    30                                 // 对FactoryBean获取的对象进行后置处理,返回生成的对象
    31                                 object = postProcessObjectFromFactoryBean(object, beanName);
    32                             } catch (Throwable ex) {
    33                                 throw new BeanCreationException(beanName,
    34                                                                 "Post-processing of FactoryBean's singleton object failed", ex);
    35                             } finally {
    36                                 // 单例bean的后置处理 和前置处理相反,前置添加,后置移除 移除标志,当前bean不处于创建中
    37                                 afterSingletonCreation(beanName);
    38                             }
    39                         }
    40                         // 添加到factoryBeanObjectCache中进行缓存
    41                         if (containsSingleton(beanName)) {
    42                             this.factoryBeanObjectCache.put(beanName, object);
    43                         }
    44                     }
    45                 }
    46                 return object;
    47             }
    48         } else {
    49             // 不满足第一个条件,不是单例,或者缓存中不存在,则从FactoryBean中获取对象
    50             Object object = doGetObjectFromFactoryBean(factory, beanName);
    51             // 需要后续处理
    52             if (shouldPostProcess) {
    53                 try {
    54                     // 对FactoryBean获取的对象进行后处理
    55                     // 返回生成的对象
    56                     object = postProcessObjectFromFactoryBean(object, beanName);
    57                 } catch (Throwable ex) {
    58                     throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
    59                 }
    60             }
    61             return object;
    62         }
    63     }

    分析:

    函数分两大分支:

    #1.单例且singletonObjects缓存中存在(该分支为同步方法)

    • #1.1:FactoryBean为单例,并且缓存中存在该bean对象(containsSingleton方法其实就是判断singletonObjects集合中是否存在bean对象),首先从缓存中获取factoryBean对象object,如果object=null,则从doGetObjectFromFactoryBean方法中获取对象。注意:这里再次从factoryBeanObjectCache缓存中尝试获取对象(主要是循环依赖问题,有可能这时该bean对象已经加载了,就不用再次加载了),如果缓存中已存在bean对象,则使用缓存中对象,并直接返回。
    • #1.2:如果factoryBeanObjectCache缓存中不存在对象且需要后置处理,则首先判断该bean对象是否正在被创建,如果是,则直接返回,注意这里未进行缓存;然后对单例bean进行前置添加处理(beforeSingletonCreation)、后置处理(postProcessObjectFromFactoryBean)、后置移除标志处理(afterSingletonCreation)。
    • #1.3:最后将缓存生成的bean对象

    #2.不满足(#1)中的任何一条件

    • 首先从doGetObjectFromFactoryBean方法中获取获取bean对象,如果需要后置处理,则调用postProcessObjectFromFactoryBean方法进行处理,最后返回生成过的bean对象。

    在上述分析中涉及到几个函数,下面一一进行分析。

    FactoryBeanRegistrySupport#doGetObjectFromFactoryBean

     1 private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
     2             throws BeanCreationException {
     3 
     4         Object object;
     5         try {
     6             // 如果权限不为空
     7             if (System.getSecurityManager() != null) {
     8                 AccessControlContext acc = getAccessControlContext();
     9                 try {
    10                     // 从FactoryBean中获取Bean对象[factory::getObject] 其实与else分支一样的
    11                     object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
    12                 } catch (PrivilegedActionException pae) {
    13                     throw pae.getException();
    14                 }
    15             } else {
    16                 // 如果权限为空,则从Factory中获取Bean对象
    17                 object = factory.getObject();
    18             }
    19         } catch (FactoryBeanNotInitializedException ex) {
    20             throw new BeanCurrentlyInCreationException(beanName, ex.toString());
    21         } catch (Throwable ex) {
    22             throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
    23         }
    24 
    25         // 进行一波校验
    26         // Do not accept a null value for a FactoryBean that's not fully
    27         // initialized yet: Many FactoryBeans just return null then.
    28         if (object == null) {
    29             // 如果bean正在被创建,则抛出异常
    30             if (isSingletonCurrentlyInCreation(beanName)) {
    31                 throw new BeanCurrentlyInCreationException(
    32                         beanName, "FactoryBean which is currently in creation returned null from getObject");
    33             }
    34             object = new NullBean();
    35         }
    36         return object;
    37     }

    分析:

    根据是否具有权限,通过FactoryBean#getObject获取bean对象,如果bean对象为null且正在被创建,则抛出异常,否则实例化一个NullBean对象进行返回。

    DefaultSingletonBeanRegistry#isSingletonCurrentlyInCreation

     1     /**
     2      * 正在创建中的单例 Bean 的名字的集合
     3      * Names of beans that are currently in creation.
     4      */
     5     private final Set<String> singletonsCurrentlyInCreation =
     6             Collections.newSetFromMap(new ConcurrentHashMap<>(16));
     7 
     8 public boolean isSingletonCurrentlyInCreation(String beanName) {
     9         return this.singletonsCurrentlyInCreation.contains(beanName);
    10     }

    分析:

    该函数判断bean是否正处于创建之中,该方法要与beforeSingletonCreation和afterSingletonCreation配合起来分析才能明白其重要性,他们记录了bean的加载状态,是检查当前bean是否处于创建中的关键处,对解决bean的循环依赖起着重要作用。

    DefaultSingletonBeanRegistry#beforeSingletonCreation

    1     protected void beforeSingletonCreation(String beanName) {
    2         // 这里会添加到正在创建bean的集合中
    3         // 注意第一个条件,如果存在,则为false,直接短路
    4         // 只有当第一个条件不存在[false]时,才会去进行添加操作
    5         if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    6             throw new BeanCurrentlyInCreationException(beanName);
    7         }
    8     }

    分析:

    注意这里就会将正在创建的beanName添加到singletonsCurrentlyInCreation集合中,第一个条件是判断该bean是否不会被检测。

    DefaultSingletonBeanRegistry#afterSingletonCreation

    1 protected void afterSingletonCreation(String beanName) {
    2         if (!this.inCreationCheckExclusions.contains(beanName)
    3                 && !this.singletonsCurrentlyInCreation.remove(beanName)) { // 移除
    4             // 如果移除失败,则抛出IllegalStateException异常
    5             throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    6         }
    7     }

    分析:

    afterSingletonCreation方法与beforeSingletonCreation方法的功能相反,用于将beanName移除正在创建的集合singletonsCurrentlyInCreation,表明bean创建完成。

    postProcessObjectFromFactoryBean

    该方法的默认实现,就是返回当前bean对象。

    1 // FactoryBeanRegistrySupport
    2 protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
    3         return object;
    4     }

    当然,子类可以对该方法进行重写。

     1 // AbstractAutowireCapableBeanFactory
     2 
     3     protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
     4         return applyBeanPostProcessorsAfterInitialization(object, beanName);
     5     }
     6 
     7 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
     8             throws BeansException {
     9 
    10         Object result = existingBean;
    11         // 遍历BeanPostProcessor
    12         for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    13             // 进行处理
    14             // TODO: 2019/4/2 具体处理过程需详细查看,这里先走大流程
    15             Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
    16             // 返回为空,则返回传入的Object对象
    17             if (current == null) {
    18                 return result;
    19             }
    20             // 修改result
    21             result = current;
    22         }
    23         return result;
    24     }

    分析:

    这里主要是遍历BeanPostProcessor,然后对bean对象进行处理,关于后置处理器的分析后面再做分析。

    到这里从单例缓存中获取bean对象的相应源码已分析完成,接下来看单例缓存中无bean对象时,Spring的处理流程,再次将getBean的切入点代码贴出来。

      1 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      2                               @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
      3 
      4         // .........省略从单例缓存中获取bean对象的代码
      5         } else {
      6             // Fail if we're already creating this bean instance:
      7             // We're assumably within a circular reference.
      8             // Spring只能解决单例模式下的循环依赖,在原型模式下如果存在循环依赖则抛出异常
      9             // 这里检测原型模式下,该bean是否在加载,如果在加载则抛出异常
     10             if (isPrototypeCurrentlyInCreation(beanName)) {
     11                 throw new BeanCurrentlyInCreationException(beanName);
     12             }
     13 
     14             // 如果当前容器中没有找到,则从父类容器中加载
     15             // Check if bean definition exists in this factory.
     16             BeanFactory parentBeanFactory = getParentBeanFactory();
     17             /**
     18              * 调用{@link DefaultListableBeanFactory#containsBeanDefinition(String)}方法
     19              * 其实就是在beanDefinitionMap中判断是否存在beanName对应的BeanDefinition
     20              */
     21             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
     22                 // Not found -> check parent.
     23                 // 确定原始的beanName
     24                 String nameToLookup = originalBeanName(name);
     25                 // 如果父类容器为AbstractBeanFactory,则委托父类处理
     26                 if (parentBeanFactory instanceof AbstractBeanFactory) {
     27                     return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
     28                             nameToLookup, requiredType, args, typeCheckOnly);
     29                 } else if (args != null) { // 用明确的args从parentBeanFactory中,获取Bean对象
     30                     // Delegation to parent with explicit args.
     31                     // 委托给父类构造函数getBean()处理
     32                     return (T) parentBeanFactory.getBean(nameToLookup, args);
     33                 } else if (requiredType != null) { // 用明确的requiredType从parentBeanFactory中,获取Bean对象
     34                     // No args -> delegate to standard getBean method.
     35                     // 没有args,委托给标准的getBean()处理
     36                     return parentBeanFactory.getBean(nameToLookup, requiredType);
     37                 } else {
     38                     // 直接使用nameToLookup从parentBeanFactory中获取Bean对象
     39                     return (T) parentBeanFactory.getBean(nameToLookup);
     40                 }
     41             }
     42 
     43             // 如果不仅仅是做类型检查,而是创建bean,这里需要记录
     44             if (!typeCheckOnly) {
     45                 markBeanAsCreated(beanName);
     46             }
     47 
     48             try {
     49                 /**
     50                  * 从容器中获取beanName对应的GenericBeanDefinition对象,并转换成RootBeanDefinition对象
     51                  * GenericBeanDefinition的创建{@link BeanDefinitionReaderUtils#createBeanDefinition}方法
     52                  */
     53                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
     54                 // 检查合并的BeanDefinition
     55                 checkMergedBeanDefinition(mbd, beanName, args);
     56 
     57                 // Guarantee initialization of beans that the current bean depends on.
     58                 // 处理所依赖的bean
     59                 String[] dependsOn = mbd.getDependsOn();
     60                 if (dependsOn != null) {
     61                     for (String dep : dependsOn) {
     62                         // 若给定的依赖bean已经注册为依赖给定的bean
     63                         // 即循环依赖情况,抛出BeanCreationException异常
     64                         if (isDependent(beanName, dep)) {
     65                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     66                                                             "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
     67                         }
     68                         // 缓存依赖调用
     69                         registerDependentBean(dep, beanName);
     70                         try {
     71                             // 递归处理依赖 Bean
     72                             getBean(dep);
     73                         } catch (NoSuchBeanDefinitionException ex) {
     74                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     75                                                             "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
     76                         }
     77                     }
     78                 }
     79                 // bean实例化
     80                 // Create bean instance.
     81                 // 单例模式
     82                 /**
     83                  * 这里有个已创建bean的重要方法createBean
     84                  * {@link AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])}
     85                  */
     86                 if (mbd.isSingleton()) {
     87                     sharedInstance = getSingleton(beanName, () -> {
     88                         try {
     89                             return createBean(beanName, mbd, args);
     90                         } catch (BeansException ex) {
     91                             // Explicitly remove instance from singleton cache: It might have been put there
     92                             // eagerly by the creation process, to allow for circular reference resolution.
     93                             // Also remove any beans that received a temporary reference to the bean.
     94                             // 显式从单例缓存中删除Bean实例
     95                             // 因为单例模式下为了解决循环依赖,可能它已经存在,所以销毁它
     96                             destroySingleton(beanName);
     97                             throw ex;
     98                         }
     99                     });
    100                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    101                 } else if (mbd.isPrototype()) { // 原型模式
    102                     // It's a prototype -> create a new instance.
    103                     Object prototypeInstance = null;
    104                     try {
    105                         // 前置处理
    106                         beforePrototypeCreation(beanName);
    107                         /**
    108                          * 创建bean {@link AbstractAutowireCapableBeanFactory#createBean}
    109                          */
    110                         prototypeInstance = createBean(beanName, mbd, args);
    111                     } finally {
    112                         /**
    113                          * 后置处理 与前置处理相反从{@link prototypesCurrentlyInCreation}中移除
    114                          */
    115                         afterPrototypeCreation(beanName);
    116                     }
    117                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    118                 } else { //其他作用域
    119                     // 获得scopeName对应的Scope对象
    120                     String scopeName = mbd.getScope();
    121                     final Scope scope = this.scopes.get(scopeName);
    122                     if (scope == null) {
    123                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    124                     }
    125                     try {
    126                         /**
    127                          * 从指定的scope下创建bean
    128                          * {@link SimpleThreadScope#get方法}
    129                          */
    130                         Object scopedInstance = scope.get(beanName, () -> {
    131                             beforePrototypeCreation(beanName);
    132                             try {
    133                                 return createBean(beanName, mbd, args);
    134                             } finally {
    135                                 afterPrototypeCreation(beanName);
    136                             }
    137                         });
    138                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    139                     } catch (IllegalStateException ex) {
    140                         throw new BeanCreationException(beanName,
    141                                                         "Scope '" + scopeName + "' is not active for the current thread; consider " +
    142                                                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    143                                                         ex);
    144                     }
    145                 }
    146             } catch (BeansException ex) {
    147                 cleanupAfterBeanCreationFailure(beanName);
    148                 throw ex;
    149             }
    150         }
    151 
    152         // 检查需要的类型是否符合bean的实际类型
    153         // Check if required type matches the type of the actual bean instance.
    154         if (requiredType != null && !requiredType.isInstance(bean)) {
    155             try {
    156                 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    157                 if (convertedBean == null) {
    158                     throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    159                 }
    160                 return convertedBean;
    161             } catch (TypeMismatchException ex) {
    162                 if (logger.isTraceEnabled()) {
    163                     logger.trace("Failed to convert bean '" + name + "' to required type '" +
    164                                          ClassUtils.getQualifiedName(requiredType) + "'", ex);
    165                 }
    166                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    167             }
    168         }
    169         return (T) bean;
    170     }

    分析:

    #1.首先通过AbstractBeanFactory#isPrototypeCurrentlyInCreation检查bean对象是否处于原型模式下的循环依赖,因为Spring只能解决单例模式下的循环依赖,如果在原型模式下也存在该bean对象,则会抛出异常。

     1 // AbstractBeanFactory
     2     /**
     3      * 原型模式下存储beanName的ThreadLocal<br/>
     4      * Names of beans that are currently in creation.
     5      */
     6     private final ThreadLocal<Object> prototypesCurrentlyInCreation =
     7             new NamedThreadLocal<>("Prototype beans currently in creation");
     8     protected boolean isPrototypeCurrentlyInCreation(String beanName) {
     9         Object curVal = this.prototypesCurrentlyInCreation.get();
    10         return (curVal != null &&
    11                 (curVal.equals(beanName) //相等
    12                         || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); // 包含
    13     }
    • 这里就是检查原型模式的ThreadLocal中是否已经存在对应的beanName。

    #2.AbstractBeanFactory#getParentBeanFactory检查其父类BeanFactory是否存在,如果存在且beanDefinitionMap中不存在该BeanDefinition,则委托其父类通过getBean方法获取bean对象。注意这里首先会通过originalBeanName方法获取原始beanName。

    1 // AbstractBeanFactory
    2     protected String originalBeanName(String name) {
    3         String beanName = transformedBeanName(name);
    4         if (name.startsWith(FACTORY_BEAN_PREFIX)) {
    5             // 如果beanName以&开头,则在加上&进行返回 因为transformedBeanName中会去掉&
    6             beanName = FACTORY_BEAN_PREFIX + beanName;
    7         }
    8         return beanName;
    9     }
    • 首先通过transformedBeanName(该方法前面已经分析)获取真正的beanName,如果name以"&"开头,则将beanName加上"&"符号,因为transformedBeanName方法会去掉"&"符号。

    #3.判断bean是否需要做类型检查,如果不仅仅做类型检查,则需要调用markBeanAsCreated函数进行记录。

     1 // AbstractBeanFactory
     2     /**
     3      * 已创建Bean的名字集合<br/>
     4      * Names of beans that have already been created at least once.
     5      */
     6     private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
     7 
     8 
     9 protected void markBeanAsCreated(String beanName) {
    10         // 没有创建
    11         if (!this.alreadyCreated.contains(beanName)) {
    12             // 做同步
    13             synchronized (this.mergedBeanDefinitions) {
    14                 // 再次进行检查,DoubleCheck模式
    15                 if (!this.alreadyCreated.contains(beanName)) {
    16                     // Let the bean definition get re-merged now that we're actually creating
    17                     // the bean... just in case some of its metadata changed in the meantime.
    18                     // 从mergedBeanDefinitions中删除beanName,并在下次访问时重新创建它
    19                     clearMergedBeanDefinition(beanName);
    20                     // 添加到已创建bean集合中
    21                     this.alreadyCreated.add(beanName);
    22                 }
    23             }
    24         }
    25     }

    #4. 接下来将对BeanDefinition进行转换,因为最开始创建的BeanDefinition类型为GenericBeanDefinition,getMergedLocalBeanDefinition方法在前面已经进行了分析,这里不在赘述。

    #5.调用checkMergedBeanDefinition对转换后的RootBeanDefinition,如果RootBeanDefinition仍为抽象的,则抛出异常,这里抽象的对象还不能进行实例化。代码如下:

    1 // AbstractBeanFactory
    2 protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
    3             throws BeanDefinitionStoreException {
    4 
    5         if (mbd.isAbstract()) {
    6             throw new BeanIsAbstractException(beanName);
    7         }
    8     }

    #6.处理依赖,如果在加载bean对象时,发现它有依赖bean的话,那么在初始化该bean的时候需要先初始化依赖的bean对象

     1 // 处理所依赖的bean
     2                 String[] dependsOn = mbd.getDependsOn();
     3                 if (dependsOn != null) {
     4                     for (String dep : dependsOn) {
     5                         // 若给定的依赖bean已经注册为依赖给定的bean
     6                         // 即循环依赖情况,抛出BeanCreationException异常
     7                         if (isDependent(beanName, dep)) {
     8                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     9                                                             "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    10                         }
    11                         // 缓存依赖调用
    12                         registerDependentBean(dep, beanName);
    13                         try {
    14                             // 递归处理依赖 Bean
    15                             getBean(dep);
    16                         } catch (NoSuchBeanDefinitionException ex) {
    17                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    18                                                             "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
    19                         }
    20                     }
    21                 }

    分析:

    DefaultSingletonBeanRegistry#isDependent

     1 protected boolean isDependent(String beanName, String dependentBeanName) {
     2         synchronized (this.dependentBeanMap) {
     3             return isDependent(beanName, dependentBeanName, null);
     4         }
     5     }
     6 private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
     7         // alreadySeen 已经检测的依赖bean
     8         if (alreadySeen != null && alreadySeen.contains(beanName)) {
     9             return false;
    10         }
    11         // 获取原始的beanName
    12         String canonicalName = canonicalName(beanName);
    13         // 获取当前beanName的依赖集合
    14         Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
    15         // 不存在,则说明不存在注册依赖
    16         if (dependentBeans == null) {
    17             return false;
    18         }
    19         // 存在,则证明已经存在注册依赖
    20         if (dependentBeans.contains(dependentBeanName)) {
    21             return true;
    22         }
    23         // 递归检测依赖
    24         for (String transitiveDependency : dependentBeans) {
    25             if (alreadySeen == null) {
    26                 alreadySeen = new HashSet<>();
    27             }
    28             // 添加到alreadySeen
    29             alreadySeen.add(beanName);
    30             // 递推
    31             if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
    32                 return true;
    33             }
    34         }
    35         return false;
    36     }

    分析:

    这里通过一些列判断,是否依赖的bean是否已经注入,如果注入则返回true,否则返回false。

    #7.如果依赖检测通过,则调用registerDependentBean对依赖bean进行注入。

     1 // DefaultSingletonBeanRegistry
     2 
     3     /**
     4      * 保存的是依赖beanName  映射关系:beanName --> 依赖beanName的集合<br/>
     5      * Map between dependent bean names: bean name to Set of dependent bean names.
     6      */
     7     private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
     8 
     9     /**
    10      * 保存的是依赖 beanName 之间的映射关系:依赖 beanName - > beanName 的集合
    11      * Map between depending bean names: bean name to Set of bean names for the bean's dependencies.
    12      */
    13     private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
    14 
    15 public void registerDependentBean(String beanName, String dependentBeanName) {
    16         // 获取beanName
    17         String canonicalName = canonicalName(beanName);
    18 
    19         // 做同步 添加<canonicalName,<dependentBeanName>>到dependentBeanMap中
    20         synchronized (this.dependentBeanMap) {
    21             Set<String> dependentBeans =
    22                     this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
    23             if (!dependentBeans.add(dependentBeanName)) {
    24                 return;
    25             }
    26         }
    27         // 做同步 添加<canonicalName,<dependentBeanName>>到dependenciesForBeanMap中
    28         synchronized (this.dependenciesForBeanMap) {
    29             Set<String> dependenciesForBean =
    30                     this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
    31             dependenciesForBean.add(canonicalName);
    32         }
    33     }

    分析:

    这里就是就是将依赖的beanName关系添加到dependentBeanMap、dependenciesForBeanMap集合中。

    #8.最后通过getBean方法实例化依赖bean对象,该方法会在后面进行分析。

    各种scope的Bean创建

    在经过单例缓存中获取bean对象、从父类工厂中获取bean对象、处理依赖bean这三步后,接下来来到对各种scope的bean的创建。首先是单例模式bean对象的创建,我们知道singleton为Spring的bean的默认作用域,当然除了singleton之外,还有prototype、request等其他的scope。

    #1.singleton的初始化代码如下

     1 // AbstractBeanFactory
     2 
     3 if (mbd.isSingleton()) {
     4                     sharedInstance = getSingleton(beanName, () -> {
     5                         try {
     6                             return createBean(beanName, mbd, args);
     7                         } catch (BeansException ex) {
     8                             // Explicitly remove instance from singleton cache: It might have been put there
     9                             // eagerly by the creation process, to allow for circular reference resolution.
    10                             // Also remove any beans that received a temporary reference to the bean.
    11                             // 显式从单例缓存中删除Bean实例
    12                             // 因为单例模式下为了解决循环依赖,可能它已经存在,所以销毁它
    13                             destroySingleton(beanName);
    14                             throw ex;
    15                         }
    16                     });
    17                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    18 }

    分析:

    单例模式bean的初始化是从getSingleton方法开始,当然这里还有一个重要的createBean方法,该方法我们留在后面进行分析,首先来看getSingleton方法。

     1 // DefaultSingletonBeanRegistry
     2 
     3 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
     4         Assert.notNull(beanName, "Bean name must not be null");
     5         // 做同步
     6         synchronized (this.singletonObjects) {
     7             // 从缓存中检查一遍
     8             // 因为singlton模式其实已经复用了创建的bean,所以该步骤必须检查
     9             Object singletonObject = this.singletonObjects.get(beanName);
    10             // 为空,开始进行加载
    11             if (singletonObject == null) {
    12                 if (this.singletonsCurrentlyInDestruction) {
    13                     throw new BeanCreationNotAllowedException(beanName,
    14                                                               "Singleton bean creation not allowed while singletons of this factory are in destruction " +
    15                                                                       "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
    16                 }
    17                 if (logger.isDebugEnabled()) {
    18                     logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
    19                 }
    20                 // 加载前置处理 其实就是打一个标记
    21                 beforeSingletonCreation(beanName);
    22                 // 首先将新的newSingleton设置为false
    23                 boolean newSingleton = false;
    24                 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
    25                 if (recordSuppressedExceptions) {
    26                     this.suppressedExceptions = new LinkedHashSet<>();
    27                 }
    28                 try {
    29                     // 初始化bean
    30                     // 该过程其实是调用createBean()方法 这里是一个回调方法
    31                     singletonObject = singletonFactory.getObject();
    32                     newSingleton = true;
    33                 } catch (IllegalStateException ex) {
    34                     // Has the singleton object implicitly appeared in the meantime ->
    35                     // if yes, proceed with it since the exception indicates that state.
    36                     singletonObject = this.singletonObjects.get(beanName);
    37                     if (singletonObject == null) {
    38                         throw ex;
    39                     }
    40                 } catch (BeanCreationException ex) {
    41                     if (recordSuppressedExceptions) {
    42                         for (Exception suppressedException : this.suppressedExceptions) {
    43                             ex.addRelatedCause(suppressedException);
    44                         }
    45                     }
    46                     throw ex;
    47                 } finally {
    48                     if (recordSuppressedExceptions) {
    49                         this.suppressedExceptions = null;
    50                     }
    51                     // 一堆异常处理后,进行后置处理 移除标志
    52                     afterSingletonCreation(beanName);
    53                 }
    54                 // 新的bean 加入缓存中
    55                 if (newSingleton) {
    56                     addSingleton(beanName, singletonObject);
    57                 }
    58             }
    59             return singletonObject;
    60         }
    61     }

    分析(该方法同样为同步方法):

    该方法其实并未真正创建bean对象,获取bean对象的核心点在于singletonObject = singletonFactory.getObject(),但该方法是由createBean回调产生的。这里仅仅是做了一部分准备和预处理步骤:

    • 再次从缓存中检查bean是否已经加载过,如果缓存中存在则直接返回。
    • beforeSingletonCreation前面已经分析过,记录加载单例bean的状态,表示正在被加载。
    • 然后调用singletonFactory.getObject方法实例化bean对象
    • afterSingletonCreation前面也分析过了,移除bean正在被加载的标志。
    • 将生成的bean对象加入缓存。

    DefaultSingletonBeanRegistry#addSingleton

     1     /**
     2      * Cache of singleton objects: bean name to bean instance.
     3      * 存放的是单例 bean 的映射。
     4      * <p>
     5      * 对应关系为 bean name --> bean instance
     6      */
     7     private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
     8 
     9     /**
    10      * Cache of singleton factories: bean name to ObjectFactory.<br/>
    11      * 存放的是 ObjectFactory,可以理解为创建单例 bean 的 factory 。
    12      * <p>
    13      * 对应关系是 bean name --> ObjectFactory
    14      */
    15     private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    16 
    17     /**
    18      * Cache of early singleton objects: bean name to bean instance.<br/>
    19      * 存放的是早期的 bean,对应关系也是 bean name --> bean instance。
    20      * <p>
    21      * 它与 {@link #singletonFactories} 区别在于 earlySingletonObjects 中存放的 bean 不一定是完整。
    22      * <p>
    23      * 从 {@link #getSingleton(String)} 方法中,我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了。
    24      * 所以当在 bean 的创建过程中,就可以通过 getBean() 方法获取。
    25      * <p>
    26      * 这个 Map 也是【循环依赖】的关键所在。
    27      */
    28     private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    29 
    30     /**
    31      * 存储已经注册的单例 进行缓存<br/>
    32      * Set of registered singletons, containing the bean names in registration order.
    33      */
    34     private final Set<String> registeredSingletons = new LinkedHashSet<>(256);    
    35 
    36     protected void addSingleton(String beanName, Object singletonObject) {
    37         synchronized (this.singletonObjects) {
    38             this.singletonObjects.put(beanName, singletonObject);
    39             this.singletonFactories.remove(beanName);
    40             this.earlySingletonObjects.remove(beanName);
    41             this.registeredSingletons.add(beanName);
    42         }
    43     }

    分析:

    一个put、两个remove、一个add。

    • 由于已经实例化了bean,因此需要将单例bean进行缓存,singletonObjects.put。
    • 同理单例BeanFactory和提前曝光的bean也需要移除,singletonFactories.remove和earlySingletonObjects.remove。
    • registeredSingletons.add,已实例化的bean需要进行注册。

    #2.原型模式

     1 if (mbd.isPrototype()) { // 原型模式
     2                     // It's a prototype -> create a new instance.
     3                     Object prototypeInstance = null;
     4                     try {
     5                         // 前置处理
     6                         beforePrototypeCreation(beanName);
     7                         /**
     8                          * 创建bean {@link AbstractAutowireCapableBeanFactory#createBean}
     9                          */
    10                         prototypeInstance = createBean(beanName, mbd, args);
    11                     } finally {
    12                         /**
    13                          * 后置处理 与前置处理相反从{@link prototypesCurrentlyInCreation}中移除
    14                          */
    15                         afterPrototypeCreation(beanName);
    16                     }
    17                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    18                 }

    分析:

    原型模式下bean的初始化很简单,直接创建一个新Bean实例就可以了。

    • beforePrototypeCreation:记录加载原型模式bean的加载状态,前置处理。
    • createBean创建实例对象,该方法非常重要,后续会详细进行分析。
    • afterPrototypeCreation:移除创建时添加的标志,后置处理与beforePrototypeCreation方法功能相反。
    • 最后调用getObjectForBeanInstance获取实例,该方法在【spring源码分析】IOC容器初始化(六)中已经分析,这里不再赘述。

    AbstractBeanFactory#beforePrototypeCreation

     1    /**
     2      * 原型模式下存储beanName的ThreadLocal<br/>
     3      * Names of beans that are currently in creation.
     4      */
     5 private final ThreadLocal<Object> prototypesCurrentlyInCreation =
     6             new NamedThreadLocal<>("Prototype beans currently in creation");
     7 
     8 protected void beforePrototypeCreation(String beanName) {
     9         // 从ThreadLocal中取出对象
    10         Object curVal = this.prototypesCurrentlyInCreation.get();
    11         if (curVal == null) {
    12             // 如果为空,则设置值
    13             this.prototypesCurrentlyInCreation.set(beanName);
    14         } else if (curVal instanceof String) {
    15             // 如果curVal为String类型,则进行添加
    16             Set<String> beanNameSet = new HashSet<>(2);
    17             beanNameSet.add((String) curVal);
    18             beanNameSet.add(beanName);
    19             this.prototypesCurrentlyInCreation.set(beanNameSet);
    20         } else {
    21             // 否则将curVal转换成set集合,添加beanName
    22             Set<String> beanNameSet = (Set<String>) curVal;
    23             beanNameSet.add(beanName);
    24         }
    25     }

    分析:

    这里的前置处理就是将beanName加入ThreadLocal中,逻辑简单。

    AbstractBeanFactory#afterPrototypeCreation

     1     protected void afterPrototypeCreation(String beanName) {
     2         Object curVal = this.prototypesCurrentlyInCreation.get();
     3         if (curVal instanceof String) {
     4             this.prototypesCurrentlyInCreation.remove();
     5         } else if (curVal instanceof Set) {
     6             Set<String> beanNameSet = (Set<String>) curVal;
     7             beanNameSet.remove(beanName);
     8             if (beanNameSet.isEmpty()) {
     9                 this.prototypesCurrentlyInCreation.remove();
    10             }
    11         }
    12     }

    分析:

    后置处理与前置处理beforePrototypeCreation正好相反,将标记从ThreadLocal中移除。

    #3.其他作用域

     1 // 获得scopeName对应的Scope对象
     2                     String scopeName = mbd.getScope();
     3                     final Scope scope = this.scopes.get(scopeName);
     4                     if (scope == null) {
     5                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
     6                     }
     7                     try {
     8                         /**
     9                          * 从指定的scope下创建bean
    10                          * {@link SimpleThreadScope#get方法}
    11                          */
    12                         Object scopedInstance = scope.get(beanName, () -> {
    13                             beforePrototypeCreation(beanName);
    14                             try {
    15                                 return createBean(beanName, mbd, args);
    16                             } finally {
    17                                 afterPrototypeCreation(beanName);
    18                             }
    19                         });
    20                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    21                     } catch (IllegalStateException ex) {
    22                         throw new BeanCreationException(beanName,
    23                                                         "Scope '" + scopeName + "' is not active for the current thread; consider " +
    24                                                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    25                                                         ex);
    26                     }
    27                 }
    28             } catch (BeansException ex) {
    29                 cleanupAfterBeanCreationFailure(beanName);
    30                 throw ex;
    31             }

    分析:

    其他作用域bean的创建过程与原型模式的流程一样,只是获取bean的方式变成了Scope#get(String name,ObjectFactory<?> objectFactory)。

     1 //  SimpleThreadScope
     2 public Object get(String name, ObjectFactory<?> objectFactory) {
     3         // 获取scope缓存
     4         Map<String, Object> scope = this.threadScope.get();
     5         Object scopedObject = scope.get(name);
     6         if (scopedObject == null) {
     7             // 这里getObject也是进行方法回调
     8             scopedObject = objectFactory.getObject();
     9             // 加入缓存
    10             scope.put(name, scopedObject);
    11         }
    12         return scopedObject;
    13     }

    这里仅仅是Scope接口的一种实现,该接口还有其他多种实现,其具体源码可查看相应实现类:

    至此,Bean加载的大致流程已分析完毕,当然本篇文章并未分析一个很重要的函数createBean,该函数留在后续的文章继续分析。


    by Shawn Chen,2019.04.22,下午。

  • 相关阅读:
    Android提高UI性能技巧
    POJ-1785-Binary Search Heap Construction(笛卡尔树)
    atitit。企业组织与软件project的策略 战略 趋势 原则 attilax 大总结
    Remove Duplicates from Sorted List II 解答(有个比較特殊的case leetcode OJ没有覆盖)
    强名称程序集(strong name assembly)——为程序集赋予强名称
    虚函数练习:交通工具信息
    99 位职业设计师 99 个设计谏言
    在智能创业的风口鼓风,全国首个民间资本为主的物联网行业投融资平台诞生!
    具体解释。。设计模式5——DAO。。studying
    Android新控件RecyclerView剖析
  • 原文地址:https://www.cnblogs.com/developer_chan/p/10740664.html
Copyright © 2011-2022 走看看