zoukankan      html  css  js  c++  java
  • spring源码学习之bean的加载(一)

      对XML文件的解析基本上已经大致的走了一遍,虽然没有能吸收多少,但是脑子中总是有些印象的,接下来看下spring中的bean的加载,这个比xml解析复杂的多。
    这个加载,在我们使用的时候基本上是:
    BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beanFactory.xml"));
    MyTestBean bean = (MyTestBean) beanFactory.getBean("myTestBean"); // 这个是bean的加载的使用

    一、总体掌握

    看看spring中的代码是如何实现的:
    这个是在org.springframework.beans.factory.support包下的AbstractBeanFactory类

      1 @Override
      2 public Object getBean(String name) throws BeansException {
      3     return doGetBean(name, null, null, false);
      4 }
      5 
      6 /**
      7  * Return an instance, which may be shared or independent, of the specified bean.
      8  * @param name the name of the bean to retrieve
      9  * @param requiredType the required type of the bean to retrieve
     10  * @param args arguments to use when creating a bean instance using explicit arguments
     11  * (only applied when creating a new instance as opposed to retrieving an existing one)
     12  * @param typeCheckOnly whether the instance is obtained for a type check,
     13  * not for actual use
     14  * @return an instance of the bean
     15  * @throws BeansException if the bean could not be created
     16  */
     17 @SuppressWarnings("unchecked")
     18 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
     19         @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
     20 
     21     // 提取对应的beanName
     22     final String beanName = transformedBeanName(name);
     23     Object bean;
     24     
     25     /**
     26      * 检查缓存中或者实例工厂中是否有对应的实例
     27      * 为什么会首先使用这段代码呢?
     28      * 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候是为了避免循环依赖
     29      *spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
     30      * 也就是将ObjectFactory加入缓存中,一旦下个bean创建的时候需要依赖上个bean,则直接使用ObjectFactory  
     31      */
     32     // Eagerly check singleton cache for manually registered singletons.
     33     // 直接尝试从缓存中获取或者singletonFactories中ObjectFactory中获取
     34     Object sharedInstance = getSingleton(beanName);
     35     if (sharedInstance != null && args == null) {
     36         if (logger.isDebugEnabled()) {
     37             if (isSingletonCurrentlyInCreation(beanName)) {
     38                 logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
     39                         "' that is not fully initialized yet - a consequence of a circular reference");
     40             }
     41             else {
     42                 logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
     43             }
     44         }
     45         // 返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
     46         bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
     47     }
     48 
     49     else {
     50         // Fail if we're already creating this bean instance:
     51         // We're assumably within a circular reference.
     52         /**
     53          * 只有在单例的情况下才会尝试解决循环依赖,原型模式下,
     54          * 如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生
     55          * 当A还未创建完的时候,创建B,再次返回创建A,造成循环依赖,下面这种错误,抛出异常
     56          */
     57         if (isPrototypeCurrentlyInCreation(beanName)) {
     58             throw new BeanCurrentlyInCreationException(beanName);
     59         }
     60 
     61         // Check if bean definition exists in this factory.
     62         BeanFactory parentBeanFactory = getParentBeanFactory();
     63         // 在parentBeanFactory中检测
     64         if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
     65             // Not found -> check parent.
     66             String nameToLookup = originalBeanName(name);
     67             // 递归到BeanFactory中查找
     68             if (parentBeanFactory instanceof AbstractBeanFactory) {
     69                 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
     70                         nameToLookup, requiredType, args, typeCheckOnly);
     71             }
     72             else if (args != null) {
     73                 // Delegation to parent with explicit args.
     74                 return (T) parentBeanFactory.getBean(nameToLookup, args);
     75             }
     76             else {
     77                 // No args -> delegate to standard getBean method.
     78                 return parentBeanFactory.getBean(nameToLookup, requiredType);
     79             }
     80         }
     81         
     82         // 如果不是仅仅做类型检查则是创建bean,这里需要记录
     83         if (!typeCheckOnly) {
     84             markBeanAsCreated(beanName);
     85         }
     86 
     87         try {
     88             // 将存储XML配置文件GenericBeanDefinition转换为RootBeanDefinition
     89             // BeanName是子Bean的话同时会合并父类的相关属性
     90             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
     91             checkMergedBeanDefinition(mbd, beanName, args);
     92 
     93             // Guarantee initialization of beans that the current bean depends on.
     94             String[] dependsOn = mbd.getDependsOn();
     95             // 若存在依赖则需要递归实例化依赖bean
     96             if (dependsOn != null) {
     97                 for (String dep : dependsOn) {
     98                     if (isDependent(beanName, dep)) {
     99                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    100                                 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    101                     }
    102                     // 缓存依赖调用
    103                     registerDependentBean(dep, beanName);
    104                     try {
    105                         getBean(dep);
    106                     }
    107                     catch (NoSuchBeanDefinitionException ex) {
    108                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    109                                 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
    110                     }
    111                 }
    112             }
    113 
    114             // Create bean instance.
    115             // 实例化依赖的bean后便可以实例化mbd本身了
    116             // singleton模式的创建
    117             if (mbd.isSingleton()) {
    118                 sharedInstance = getSingleton(beanName, () -> {
    119                     try {
    120                         return createBean(beanName, mbd, args);
    121                     }
    122                     catch (BeansException ex) {
    123                         // Explicitly remove instance from singleton cache: It might have been put there
    124                         // eagerly by the creation process, to allow for circular reference resolution.
    125                         // Also remove any beans that received a temporary reference to the bean.
    126                         destroySingleton(beanName);
    127                         throw ex;
    128                     }
    129                 });
    130                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    131             }
    132             // Prototype模式创建
    133             else if (mbd.isPrototype()) {
    134                 // It's a prototype -> create a new instance.
    135                 Object prototypeInstance = null;
    136                 try {
    137                     beforePrototypeCreation(beanName);
    138                     prototypeInstance = createBean(beanName, mbd, args);
    139                 }
    140                 finally {
    141                     afterPrototypeCreation(beanName);
    142                 }
    143                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    144             }
    145             // 指定scope上实例化bean
    146             else {
    147                 String scopeName = mbd.getScope();
    148                 final Scope scope = this.scopes.get(scopeName);
    149                 if (scope == null) {
    150                     throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    151                 }
    152                 try {
    153                     Object scopedInstance = scope.get(beanName, () -> {
    154                         beforePrototypeCreation(beanName);
    155                         try {
    156                             return createBean(beanName, mbd, args);
    157                         }
    158                         finally {
    159                             afterPrototypeCreation(beanName);
    160                         }
    161                     });
    162                     bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    163                 }
    164                 catch (IllegalStateException ex) {
    165                     throw new BeanCreationException(beanName,
    166                             "Scope '" + scopeName + "' is not active for the current thread; consider " +
    167                             "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    168                             ex);
    169                 }
    170             }
    171         }
    172         catch (BeansException ex) {
    173             cleanupAfterBeanCreationFailure(beanName);
    174             throw ex;
    175         }
    176     }
    177 
    178     // Check if required type matches the type of the actual bean instance.
    179     // 检查需要的类型是否符合bean的实例类型
    180     if (requiredType != null && !requiredType.isInstance(bean)) {
    181         try {
    182             T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    183             if (convertedBean == null) {
    184                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    185             }
    186             return convertedBean;
    187         }
    188         catch (TypeMismatchException ex) {
    189             if (logger.isDebugEnabled()) {
    190                 logger.debug("Failed to convert bean '" + name + "' to required type '" +
    191                         ClassUtils.getQualifiedName(requiredType) + "'", ex);
    192             }
    193             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    194         }
    195     }
    196     return (T) bean;
    197 }

    (1)转换对应的beanName
    这里传入的参数name并不一定是beanName,可能是别名,也可能是FactoryBean,所以进行一系类的解析,这些解析内容如下
    1)去除FactoryBean的修饰符,也就是name="&aa",那么首先会去除&,而使name=aa
    2)取指定别名所表示的最终的beanName

    (2)尝试从缓存中加载单例
    单例在spring的同一个容器内只会被创建一次,后续在获取bean,就直接从单例缓存中获取了,当然,这里也只是尝试加载,
    首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况
    而在创建依赖的时候为了避免循环依赖,在spring中创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入
    到缓存中,一旦下一个bean创建的时候需要依赖上一个bean则直接使用ObjectFactory

    (3)bean的实例化
    如果缓存中得到了bean的原始状态,则需要对bean进行实例化,缓存中的记录只是最原始的bean状态,并不一定是我们最终想要的bean,
    举个例子,假如我们想对工厂bean进行处理,那么这里得到的是工厂bean的初始状态,但是我们真正想要的是工厂bean定义的factory-method
    方法中返回的bean,而getObjectForBeanInstance就是完成这个工作的

    (4)原型模式的依赖检查
    只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还没创建完成的时候,因为
    对B的创建再次返回创建A,造成循环依赖,也就是(isPrototypeCurrentlyInCreation(beanName))为true的情况

    (5)检测parentBeanFactory
    从代码上看,如果缓存没有数据的话,直接转到父类工厂上去加载了,这是为什么?可能我们忽略了
    parentBeanFactory != null && !containsBeanDefinition(beanName)这里面判断条件,parentBeanFactory != null,parentBeanFactory如果为空,
    其他一切都是浮云,但是还有一个条件,!containsBeanDefinition(beanName),它是在检测如果当前加载的XML配置文件中,不包含beanName多对应的
    配置,只能去parentBeanFactory中尝试,然后再去递归的调用递归方法

    (6)将存储XML配置文件GenericBeanDefinition转换为RootBeanDefinition
    因为从XML配置文件中读取到的bean信息存储在GenericBeanDefinition中,但是所有的bean的后续处理都是针对于RootBeanDefinition,
    所以这里需要进行一个转换,转换的同时,如果父类bean不为空的话,则会一并合并父类属性

    (7)寻找依赖
    因为bean的初始化过程很肯能用到某些属性,而某些属性可能是动态配置的,并且配置成依赖其他的bean,那么这个时候必须先加载依赖的bean,
    spring的加载顺序中,在初始化一个bean的时候,首先会初始化这个bean所对应的依赖

    (8)针对不同的scope进行bean的创建
    spring根据不同的配置进行不同的初始化策略,默认的是singleton

    (9)类型转换
    程序到这里已经基本结束了,通常对该方法的调用参数requireType是为空的,但是可能会存在这样的情况,返回的bean其实是个String,但是
    requireType却传入的是Integer类型,那么这时候本步骤就起作用了,他的功能是将返回的bean转换为requireType所指定的类型。

    二、剥离,逐一分析

    1、FactoryBean的使用

    一般情况下,spring通过反射机制,利用bean的class属性指定实现类来实例化bean。在某些情况下,实例化bean的过程比较复杂,按照传统的方式,
    则需要在bean的配置中提供大量的配置信息,配置方式的灵活性是受限的,spring为此提供了一个org.springframework.beans.factory.FactoryBean
    工厂类接口,用户可以实现该接口定制实例化bean的逻辑

    FactoryBean接口对于spring来说,占有重要地位,spring自身就提供了70多个FactoryBean的实现,从spring 3.0开始,FactoryBean开始支持泛型
    接口声明为:

    1 public interface FactoryBean<T> {
    2     T getObject() throws Exception;
    3     Class<?> getObjectType();
    4     default boolean isSingleton() {
    5         return true;
    6     }
    7 }

    接口中定义的三个方法:
    1)T getObject():返回由FactoryBean创建的bean实例,如果isSignleton()返回的是true,则该实例会方放到spring容器中单实例缓存池中
    2)default boolean isSingleton():判断创建bean的scope
    3)Class<?> getObjectType():返回创建bean的类型

    2、缓存中获取单例bean

    单例在spring的同一容器中只会被创建一次,然后再获取bean直接从单例缓存中获取,当然,这里也只是尝试加载,首先尝试从缓存中加载,
    然后再次尝试从singletonFactories中加载,因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,
    spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建的时候依赖上个bean
    则直接使用ObjectFactory
    下面的额源码是在org.springframework.beans.factory.support包下DefaultSingletonBeanRegistry中

     1 @Override
     2 @Nullable
     3 public Object getSingleton(String beanName) {
     4     return getSingleton(beanName, true);
     5 }
     6 
     7 /**
     8  * Return the (raw) singleton object registered under the given name.
     9  * <p>Checks already instantiated singletons and also allows for an early
    10  * reference to a currently created singleton (resolving a circular reference).
    11  * @param beanName the name of the bean to look for
    12  * @param allowEarlyReference whether early references should be created or not
    13  * @return the registered singleton object, or {@code null} if none found
    14  */
    15 @Nullable
    16 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    17     // 检查缓存中是否存在实例
    18     Object singletonObject = this.singletonObjects.get(beanName);
    19     if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    20         // 如果为空,则锁定全局变量并进行处理
    21         synchronized (this.singletonObjects) {
    22             // 如果此bean正在加载则不处理
    23             singletonObject = this.earlySingletonObjects.get(beanName);
    24             if (singletonObject == null && allowEarlyReference) {
    25                 // ObjectFactory初始化策略存储在singletonFactories
    26                 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    27                 if (singletonFactory != null) {
    28                     // 调用预先设定好的getObject()方法
    29                     singletonObject = singletonFactory.getObject();
    30                     // 记录在缓存中earlySingletonObjects和singletonFactories互斥
    31                     this.earlySingletonObjects.put(beanName, singletonObject);
    32                     this.singletonFactories.remove(beanName);
    33                 }
    34             }
    35         }
    36     }
    37     return singletonObject;
    38 }

    这个方法首先尝试从singletonObjects里面获取实例,如果获取不到,再从earlySingletonObjects中获取,如果还获取不到,尝试从
    singletonFactories中获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject()来创建bean,并放到earlySingletonObjects中去,
    并且从singletonFactories中remove掉ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,这里有几个不同的map:
    singletonObjects:用于保存BeanName和创建bean实例之间的关系,bean name -> bean instance
    singletonFactories:用于保存BeanName和创建bean工厂之间的关系,bean name -> ObjectFactory
    earlySingletonObjects:用于保存BeanName和创建bean实例之间的关系,与ingletonObjects不同的是,当一个单例bean被放到这里面后,那么当bean
    还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用
    registeredSingletons:用来保存所有当前已存在的bean

    3、从bean的实例中获取对象

    在getBean()方法中,getObjectForBeanInstance是个高频使用的方法,无论是从缓存中获取bean还是根据不同的scope策略加载bean,总之,得到bean
    的实例后,我们第一步要做的就是调用这个方法来检测一下正确性,其实就是用于检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该
    bean对应的FactoryBean实例中的getObject()作为返回值

    无论是从缓存中获取到bean还是从不同的scope策略中加载的bean都是最原始的bean状态,并不一定是我们最终想要的bean,而getObjectForBeanInstance
    方法就是完成这个工作的
    该方法是在org.springframework.beans.factory.support包下的AbstractBeanFactory类:

     1 protected Object getObjectForBeanInstance(
     2         Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
     3 
     4     // Don't let calling code try to dereference the factory if the bean isn't a factory.
     5     // 如果指定的name是工厂相关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过
     6     if (BeanFactoryUtils.isFactoryDereference(name)) {
     7         if (beanInstance instanceof NullBean) {
     8             return beanInstance;
     9         }
    10         if (!(beanInstance instanceof FactoryBean)) {
    11             throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
    12         }
    13     }
    14 
    15     // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    16     // If it's a FactoryBean, we use it to create a bean instance, unless the
    17     // caller actually wants a reference to the factory.
    18     // 现在我们有了一个bean的实例,这个实例可能是正常的bean或者是FactoryBean类型的
    19     // 如果是FactoryBean我们使用它创建实例
    20     // 但是如果用户想要直接获取工厂实例而不是工厂的getObject()方法对应的实例,那么传入的name应该加入前缀&
    21     if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
    22         return beanInstance;
    23     }
    24 
    25     Object object = null;
    26     if (mbd == null) {
    27         // 尝试从缓存中加载bean
    28         object = getCachedObjectForFactoryBean(beanName);
    29     }
    30     if (object == null) {
    31         // Return bean instance from factory.
    32         // 到这里已经明确知道beanInstance一定是FactoryBean
    33         FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
    34         // Caches object obtained from FactoryBean if it is a singleton.
    35         // containsBeanDefinition检测beanDefinitionMap中也就是所有已经记载的类中检测是否定义beanName
    36         if (mbd == null && containsBeanDefinition(beanName)) {
    37             // 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
    38             // 如果指定BeanName 是子bean的话同时合并父类的相关属性
    39             mbd = getMergedLocalBeanDefinition(beanName);
    40         }
    41         // 是否是用户定义的,而不是应用程序本身定义的
    42         boolean synthetic = (mbd != null && mbd.isSynthetic());
    43         object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    44     }
    45     return object;
    46 }

    这个方法其实大部分代码是在做一些功能性判断,真正的核心的代码交给了getObjectFromFactoryBean()方法来处理
    此方法是在org.springframework.beans.factory.support包下的FactoryBeanRegistrySupport类
    这个和作者在书中的源码有些不同的地方,应该是做了一些优化,注意一下这个地方,有些源码还是不懂为啥那么做

     1 /**
     2  * Obtain an object to expose from the given FactoryBean.
     3  * @param factory the FactoryBean instance
     4  * @param beanName the name of the bean
     5  * @param shouldPostProcess whether the bean is subject to post-processing
     6  * @return the object obtained from the FactoryBean
     7  * @throws BeanCreationException if FactoryBean object creation failed
     8  * @see org.springframework.beans.factory.FactoryBean#getObject()
     9  */
    10 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    11     // 如果是单例模式
    12     if (factory.isSingleton() && containsSingleton(beanName)) {
    13         synchronized (getSingletonMutex()) {
    14             // 从缓存中获取bean实例
    15             Object object = this.factoryBeanObjectCache.get(beanName);
    16             if (object == null) {
    17                 // 从工厂bean中获取bean实例
    18                 object = doGetObjectFromFactoryBean(factory, beanName);
    19                 // Only post-process and store if not put there already during getObject() call above
    20                 // (e.g. because of circular reference processing triggered by custom getBean calls)
    21                 Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
    22                 if (alreadyThere != null) {
    23                     object = alreadyThere;
    24                 }
    25                 else {
    26                     if (shouldPostProcess) {
    27                         if (isSingletonCurrentlyInCreation(beanName)) {
    28                             // Temporarily return non-post-processed object, not storing it yet..
    29                             return object;
    30                         }
    31                         beforeSingletonCreation(beanName);
    32                         try {
    33                             object = postProcessObjectFromFactoryBean(object, beanName);
    34                         }
    35                         catch (Throwable ex) {
    36                             throw new BeanCreationException(beanName,
    37                                     "Post-processing of FactoryBean's singleton object failed", ex);
    38                         }
    39                         finally {
    40                             afterSingletonCreation(beanName);
    41                         }
    42                     }
    43                     if (containsSingleton(beanName)) {
    44                         this.factoryBeanObjectCache.put(beanName, object);
    45                     }
    46                 }
    47             }
    48             return object;
    49         }
    50     }
    51     else {
    52         Object object = doGetObjectFromFactoryBean(factory, beanName);    
    53         if (shouldPostProcess) {
    54             // bean需要做后续处理
    55             try {
    56                 object = postProcessObjectFromFactoryBean(object, beanName);
    57             }
    58             catch (Throwable ex) {
    59                 throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
    60             }
    61         }
    62         return object;
    63     }
    64 }

    从工厂中获取bean实例的代码在doGetObjectFromFactoryBean()方法中,来看看
    此方法是在org.springframework.beans.factory.support包下的FactoryBeanRegistrySupport类

     1 /**
     2  * Obtain an object to expose from the given FactoryBean. --> 获得一个bean实例从所给的工厂bean中
     3  * @param factory the FactoryBean instance
     4  * @param beanName the name of the bean
     5  * @return the object obtained from the FactoryBean
     6  * @throws BeanCreationException if FactoryBean object creation failed
     7  * @see org.springframework.beans.factory.FactoryBean#getObject()
     8  */
     9 private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
    10         throws BeanCreationException {
    11 
    12     Object object;
    13     try {
    14         // 需要权限验证 access是权限的意思
    15         if (System.getSecurityManager() != null) {
    16             AccessControlContext acc = getAccessControlContext();
    17             try {
    18                 object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
    19             }
    20             catch (PrivilegedActionException pae) {
    21                 throw pae.getException();
    22             }
    23         }
    24         else {
    25             // 在工厂中创建bean实例
    26             object = factory.getObject();
    27         }
    28     }
    29     catch (FactoryBeanNotInitializedException ex) {
    30         throw new BeanCurrentlyInCreationException(beanName, ex.toString());
    31     }
    32     catch (Throwable ex) {
    33         throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
    34     }
    35 
    36     // Do not accept a null value for a FactoryBean that's not fully
    37     // initialized yet: Many FactoryBeans just return null then.
    38     if (object == null) {
    39         if (isSingletonCurrentlyInCreation(beanName)) {
    40             throw new BeanCurrentlyInCreationException(
    41                     beanName, "FactoryBean which is currently in creation returned null from getObject");
    42         }
    43         object = new NullBean();
    44     }
    45     return object;
    46 }

    这个能得到实例化的bean了,但是根据shouldPostProcess来进行后续的bean处理,走的是postProcessObjectFromFactoryBean()方法
    org.springframework.beans.factory.support包下的FactoryBeanRegistrySupport类,这个是抽象类,找到实现该方法的类,那就是
    org.springframework.beans.factory.support包下的AbstractAutowireCapableBeanFactory类,看一下这个类中源码实现:

     1 /**
     2  * Applies the {@code postProcessAfterInitialization} callback of all
     3  * registered BeanPostProcessors, giving them a chance to post-process the
     4  * object obtained from FactoryBeans (for example, to auto-proxy them).
     5  * @see #applyBeanPostProcessorsAfterInitialization
     6  */
     7 @Override
     8 protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
     9     return applyBeanPostProcessorsAfterInitialization(object, beanName);
    10 }
    11 
    12 @Override
    13 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    14         throws BeansException {
    15 
    16     Object result = existingBean;
    17     for (BeanPostProcessor processor : getBeanPostProcessors()) {
    18         Object current = processor.postProcessAfterInitialization(result, beanName);
    19         if (current == null) {
    20             return result;
    21         }
    22         result = current;
    23     }
    24     return result;
    25 }

    对于后续处理操作,作者在这里没有详细介绍,后续会有详细介绍,这里就不详细讲解了,我也没法记下来,只能跟着作者的思路来进行探索了,
    这里作者提出了一条总结:spring获取bean的规则只有一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization
    方法进行处理,也就是上面方法中的Object current = processor.postProcessAfterInitialization(result, beanName);这一行代码,可以针对此特性设计自己的
    设计逻辑

    4、获取单例

    之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean,就需要从头开始bean的加载过程了,而spring中使用了
    getSingleton()的重载方法实现bean的加载过程

     1 /**
     2  * Return the (raw) singleton object registered under the given name,
     3  * creating and registering a new one if none registered yet.
     4  * @param beanName the name of the bean
     5  * @param singletonFactory the ObjectFactory to lazily create the singleton
     6  * with, if necessary
     7  * @return the registered singleton object
     8  */
     9 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    10     Assert.notNull(beanName, "Bean name must not be null");
    11     // 全局变量需要同步
    12     synchronized (this.singletonObjects) {
    13         // 首先检查对应的bean是否已经加载过,因为singleton模式其实就是复用以创建的bean,所以这一步是必须的
    14         Object singletonObject = this.singletonObjects.get(beanName);
    15         // 如果为空才可以进行singleton的bean的初始化
    16         if (singletonObject == null) {
    17             if (this.singletonsCurrentlyInDestruction) {
    18                 throw new BeanCreationNotAllowedException(beanName,
    19                         "Singleton bean creation not allowed while singletons of this factory are in destruction " +
    20                         "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
    21             }
    22             if (logger.isDebugEnabled()) {
    23                 logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
    24             }
    25             beforeSingletonCreation(beanName);
    26             boolean newSingleton = false;
    27             boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
    28             if (recordSuppressedExceptions) {
    29                 this.suppressedExceptions = new LinkedHashSet<>();
    30             }
    31             try {
    32                 // 初始化bean
    33                 singletonObject = singletonFactory.getObject();
    34                 newSingleton = true;
    35             }
    36             catch (IllegalStateException ex) {
    37                 // Has the singleton object implicitly appeared in the meantime ->
    38                 // if yes, proceed with it since the exception indicates that state.
    39                 singletonObject = this.singletonObjects.get(beanName);
    40                 if (singletonObject == null) {
    41                     throw ex;
    42                 }
    43             }
    44             catch (BeanCreationException ex) {
    45                 if (recordSuppressedExceptions) {
    46                     for (Exception suppressedException : this.suppressedExceptions) {
    47                         ex.addRelatedCause(suppressedException);
    48                     }
    49                 }
    50                 throw ex;
    51             }
    52             finally {
    53                 if (recordSuppressedExceptions) {
    54                     this.suppressedExceptions = null;
    55                 }
    56                 afterSingletonCreation(beanName);
    57             }
    58             if (newSingleton) {
    59                 // 加入缓存中
    60                 addSingleton(beanName, singletonObject);
    61             }
    62         }
    63         return singletonObject;
    64     }
    65 }

    上述代码中其实使用了回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,而真正的获取单例bean的方法其实并不是在此方法中实现,
    其逻辑是在ObjectFactory类型的实例singletonFactory中实现的,而这些准备和处理操作包括如下:
    (1)检查缓存中是否已经加载过
    (2)若没有加载,则记录beanName的正在加载状态
    (3)加载单例前记录加载状态

    可能你会觉得beforeSingletonCreation方法是个空实现,里面没有任何逻辑,但其实不是,这个函数中做了一个很重要的操作:记录加载状态,也就是
    通过this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中,这样就可以对循环依赖进行检测 同一个类中

    1 protected void beforeSingletonCreation(String beanName) {
    2     if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    3         throw new BeanCurrentlyInCreationException(beanName);
    4     }
    5 }

    (4)通过调用参数传入的ObjectFactory的个体Object方法实例化bean
    (5)加载单例后的处理方法调用
    同步骤3的记录加载状态相似,当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录,同一个类中

    1 protected void afterSingletonCreation(String beanName) {
    2     if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
    3         throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    4     }
    5 }

    (6)将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态 同一个类中

    1 protected void addSingleton(String beanName, Object singletonObject) {
    2     synchronized (this.singletonObjects) {
    3         this.singletonObjects.put(beanName, singletonObject);
    4         this.singletonFactories.remove(beanName);
    5         this.earlySingletonObjects.remove(beanName);
    6         this.registeredSingletons.add(beanName);
    7     }
    8 }

    (7)返回处理结果
    虽然我们了解了加载bean的逻辑架构,但是现在我们并没有开始对bean加载功能进行探索,之前提到过,bean的加载逻辑实在传入的ObjectFactory类型的参数
    singletonFactory中定义的,我们反推参数的获取,得到以下代码:这我就不会往回反推参数,全局搜索的。。。
    这段代码是在org.springframework.beans.factory.support包下AbstractBeanFactory类中,doGetBean()方法

     1 sharedInstance = getSingleton(beanName, () -> {
     2     try {
     3         return createBean(beanName, mbd, args);
     4     }
     5     catch (BeansException ex) {
     6         // Explicitly remove instance from singleton cache: It might have been put there
     7         // eagerly by the creation process, to allow for circular reference resolution.
     8         // Also remove any beans that received a temporary reference to the bean.
     9         destroySingleton(beanName);
    10         throw ex;
    11     }
    12 });

    ObjectFactory的核心部分只调用了createBean()方法,继续探索createBean()

    5、准备创建bean
    这里作者提出了一点在探索spring源码的过程中的一点规律:一个真正干活的函数其实是以do开头的,比如doGetObjectFromFactoryBean,而给我们错觉的函数
    getObjectFromFactoryBean,其实只是从全局角度去做一些统筹工作,这个规则对createBean也不例外,看createBean如何统筹工作:

     1 /**
     2  * Central method of this class: creates a bean instance,
     3  * populates the bean instance, applies post-processors, etc.
     4  * @see #doCreateBean
     5  */
     6 @Override
     7 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
     8         throws BeanCreationException {
     9 
    10     if (logger.isDebugEnabled()) {
    11         logger.debug("Creating instance of bean '" + beanName + "'");
    12     }
    13     RootBeanDefinition mbdToUse = mbd;
    14 
    15     // Make sure bean class is actually resolved at this point, and
    16     // clone the bean definition in case of a dynamically resolved Class
    17     // which cannot be stored in the shared merged bean definition.
    18     // 锁定class,根据设置的class属性或者根据beanName来解析Class,具体在实现逻辑在resolveBeanClass()方法中
    19     Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    20     if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    21         mbdToUse = new RootBeanDefinition(mbd);
    22         mbdToUse.setBeanClass(resolvedClass);
    23     }
    24 
    25     // Prepare method overrides.
    26     // 验证及准备覆盖方法
    27     try {
    28         // 
    29         mbdToUse.prepareMethodOverrides();
    30     }
    31     catch (BeanDefinitionValidationException ex) {
    32         throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    33                 beanName, "Validation of method overrides failed", ex);
    34     }
    35 
    36     try {
    37         // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    38         // 给BeanPostProcessors一个机会来返回代理来替代真正的实例
    39         Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    40         if (bean != null) {
    41             return bean;
    42         }
    43     }
    44     catch (Throwable ex) {
    45         throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
    46                 "BeanPostProcessor before instantiation of bean failed", ex);
    47     }
    48 
    49     try {
    50         // 真正的创建bean的代码在这个方法中
    51         Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    52         if (logger.isDebugEnabled()) {
    53             logger.debug("Finished creating instance of bean '" + beanName + "'");
    54         }
    55         return beanInstance;
    56     }
    57     catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    58         // A previously detected exception with proper bean creation context already,
    59         // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
    60         throw ex;
    61     }
    62     catch (Throwable ex) {
    63         throw new BeanCreationException(
    64                 mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    65     }
    66 }

    来看下具体步骤和功能
    (1)根据设置的class属性或者是beanName来解析Class
    (2)对override属性进行标记和验证
    这个其实spring中没有override-method这样的配置,但是spring是存在lookup-method和replace-method的,而这两个配置的加载其实
    就是将配置统一存放到BeanDefinition中的methodOverride属性里,这个函数的操作其实就是针对这两个属性
    (3)应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作
    (4)创建bean

    5.1 处理override属性

    prepareMethodOverrides()方法在org.springframework.beans.factory.support包下的AbstractBeanDefinition类中

     1 public void prepareMethodOverrides() throws BeanDefinitionValidationException {
     2     // Check that lookup methods exists.
     3     if (hasMethodOverrides()) {
     4         Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
     5         synchronized (overrides) {
     6             for (MethodOverride mo : overrides) {
     7                 prepareMethodOverride(mo);
     8             }
     9         }
    10     }
    11 }
    12 
    13 //继续看prepareMethodOverride(mo)方法的源码,在同一个类中:
    14 /**
    15  * Validate and prepare the given method override.
    16  * Checks for existence of a method with the specified name,
    17  * marking it as not overloaded if none found.
    18  * @param mo the MethodOverride object to validate
    19  * @throws BeanDefinitionValidationException in case of validation failure
    20  */
    21 protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    22     // 获取对应类中对应方法名的个数
    23     int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
    24     if (count == 0) {
    25         throw new BeanDefinitionValidationException(
    26                 "Invalid method override: no method with name '" + mo.getMethodName() +
    27                 "' on class [" + getBeanClassName() + "]");
    28     }
    29     else if (count == 1) {
    30         // Mark override as not overloaded, to avoid the overhead of arg type checking.
    31         // 标记MethodOverride暂未被覆盖,避免参数类型的检查的开销
    32         mo.setOverloaded(false);
    33     }
    34 }

    spring是存在lookup-method和replace-method的,而这两个配置的加载其实就是将配置统一存放到BeanDefinition中的methodOverride属性里,
    这两个方法的实现原理是在bean实例化的时候检测到存在MethodOverride,会动态的为当前bean生成动态代理并使用对应的拦截器为bean做增强处理,
    相关逻辑实现在bean的实例化部分详细及讲解
    但是,对于方法的匹配来讲,如果一个类中存在若干个重载方法,那么,在函数调用及增强的时候,还需要根据参数类型进行匹配,来最终确认当前调用的是
    哪个函数。但是,spring将一部分匹配工作在这里完成了,如果当前类中的方法只有一个,那么就设置重载方法没有重载,这样在后续调用的时候便可以直接
    使用找到的方法,而不需要进行方法的参数匹配验证了,而且还可以提前对方法存在性进行验证。

    5.2 实例化的前置处理
    在真正调用doCreat方法创建bean之前调用了一个代理的方法,resolveBeforeInstantiation(beanName, mbdToUse),对BeanDefinition中属性做了前置处理,
    当然,无论其中是否有逻辑实现,我们都可以理解,因为真正的逻辑实现前后留有处理函数,也是可扩展的一种体现,但是,这并不是最重要的,在函数中
    还提供了一个短路判断,这才是最关键的部分(TODO:这里不是很懂,为什么这个短路操作最关键!!!)
    if (bean != null) {
      return bean;
    }
    当前置处理返回的结果如果不为空,那么直接略过后续的bean的创建而直接返回结果,这一特性虽然很容易被忽略,但是起着至关重要的作用,我们熟悉的AOP功能
    就是在这里判断的

    org.springframework.beans.factory.support包下AbstractAutowireCapableBeanFactory类中resolveBeforeInstantiation方法

     1 /**
     2  * Apply before-instantiation post-processors, resolving whether there is a
     3  * before-instantiation shortcut for the specified bean.
     4  * @param beanName the name of the bean
     5  * @param mbd the bean definition for the bean
     6  * @return the shortcut-determined bean instance, or {@code null} if none
     7  */
     8 @Nullable
     9 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    10     Object bean = null;
    11     // 如果尚未被解析
    12     if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    13         // Make sure bean class is actually resolved at this point.
    14         if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    15             Class<?> targetType = determineTargetType(beanName, mbd);
    16             if (targetType != null) {
    17                 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    18                 if (bean != null) {
    19                     bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    20                 }
    21             }
    22         }
    23         mbd.beforeInstantiationResolved = (bean != null);
    24     }
    25     return bean;
    26 }

    此方法中最吸引人的方法是applyBeanPostProcessorsBeforeInstantiation以及applyBeanPostProcessorsAfterInitialization方法,两个方法的实现非常简单,
    无非是对后处理器中的所有InstantiationAwareBeanPostProcessor类型的后处理器进行postProcessBeforeInstantiation方法和BeanPostProcessor类型的
    postProcessAfterInitialization方法的调用

    (1)实例化前的后处理应用
    bean的实例化前调用,也就是将AbstractBeanDefinition转换为BeanWrapper前处理,给子类一个修改BeanDefinition的机会,也就是说,bean通过这个方法处理之后
    可能不是我们之前的bean了

     1 @Nullable
     2 protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
     3     for (BeanPostProcessor bp : getBeanPostProcessors()) {
     4         if (bp instanceof InstantiationAwareBeanPostProcessor) {
     5             InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
     6             Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
     7             if (result != null) {
     8                 return result;
     9             }
    10         }
    11     }
    12     return null;
    13 }

    (2)实例化后的后处理应用
    在讲解从缓存中获取单例bean的时候提过,spring中的规则是在bean的初始化后尽可能保证将注册的后处理器postProcessAfterInitialization方法应用到bean中,
    因为如果返回的bean不为空,那么便不会再次经历普通bean的创建过程,所以只能在这里应用后处理器的postProcessAfterInitialization方法

     1 在讲解从缓存中获取单例bean的时候提过,spring中的规则是在bean的初始化后尽可能保证将注册的后处理器postProcessAfterInitialization方法应用到bean中,
     2 因为如果返回的bean不为空,那么便不会再次经历普通bean的创建过程,所以只能在这里应用后处理器的postProcessAfterInitialization方法
     3 @Override
     4 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
     5         throws BeansException {
     6 
     7     Object result = existingBean;
     8     for (BeanPostProcessor processor : getBeanPostProcessors()) {
     9         Object current = processor.postProcessAfterInitialization(result, beanName);
    10         if (current == null) {
    11             return result;
    12         }
    13         result = current;
    14     }
    15     return result;
    16 }

    6、循环依赖

    6.1什么是循环依赖
    循环依赖就是循环引用,就是两个或者多个bean 相互之间的持有对方,比如:CircleA调用了CircleB,CircleB引用了CircleC,CircleC引用了CircleA,则
    他们最终反应成一个环,此处不是循环调用,循环调用是方法之前的调用

    6.2spring如何解决循环依赖
    spring容器循环依赖包括构造器循环依赖和setter循环依赖,首先来定义一下循环引用类:

     1 public class TestA{
     2 
     3     private TestB testB;
     4     
     5     public void a(){
     6         testB.b();
     7     }
     8     
     9     public void setTestB(TestB testB){
    10         this.testB = testB;
    11     }
    12     
    13     public TestB getTestB(){
    14         return testB;
    15     }
    16 }
    17 
    18 public class TestB{
    19 
    20     private TestC testC;
    21     
    22     public void b(){
    23         testC.c();
    24     }
    25     
    26     public void setTestC(TestC testC){
    27         this.testC = testC;
    28     }
    29     
    30     public TestC getTestC(){
    31         return testC;
    32     }
    33 }
    34 
    35 public class TestC{
    36 
    37     private TestA testA;
    38     
    39     public void c(){
    40         testA.a();
    41     }
    42     
    43     public void setTestA(TestA testA){
    44         this.testA = testA;
    45     }
    46     
    47     public TestA getTestA(){
    48         return testA;
    49     }
    50 }

    spring 中将循环依赖的处理分成了三种情况:
    (1)构造器循环依赖
    表示通过构造器注入构成的循环依赖,次依赖是无法解决的,只能抛出异常BeanCurrentlyInCreationException异常表示循环依赖
    如在创建TestA类时,构造器需要TestB,在创建TestB 时又发现需要TestC,则又去创建TestC,最终在创建TestC时发现又需要TestA,从而形成一个环,没法创建

    spring容器将每一个正在创建的bean标识符放在一个“当前创建bean池”,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建过程中发现自己已经在
    “当前创建bean池”中,将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的bean将从“当前创建bean池”中清除掉
    看一段配置文件,来分析一下其中的,在spring中的创建过程 这其实就是上面代码在xml中的翻译

    <bean id="testA" class="com.bean.TestA">
      <constructor-arg index="0" ref="testB" />
    </bean>
    <bean id="testB" class="com.bean.TestB">
      <constructor-arg index="0" ref="testC" />
    </bean>
    <bean id="testC" class="com.bean.testC">
      <constructor-arg index="0" ref="testA" />
    </bean>

    解析:
    spring容器创建“testA”bean,首先去“当前创建bean池”查找是否当前bean正在创建,如果没发现,则继续准备其需要的构造器参数”testB“,并将”testA“
    标识符当到“当前创建bean池”
    spring容器创建“testB”bean,首先去“当前创建bean池”查找是否当前bean正在创建,如果没发现,则继续准备其需要的构造器参数”testC“,并将”testB“
    标识符当到“当前创建bean池”
    spring容器创建“testC”bean,首先去“当前创建bean池”查找是否当前bean正在创建,如果没发现,则继续准备其需要的构造器参数”testA“,并将”testC“
    标识符当到“当前创建bean池”,但是当去创建testA时,发现该bean标识符在“当前创建bean池”中,因为表示循环依赖,抛出BeanCurrentlyInCreationException

    (2)setter循环依赖
    表示通过setter注入的方式形成的循环依赖,对于setter注入造成的依赖是通过spring容器提前暴露刚完成的构造器注入但未完成其他步骤(setter注入)的
    bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使得其他bean能引用到该bean,如下代码:

    1 addSingletonFactory(beanName, new ObjectFactory(){
    2     public Object getObject(){
    3         return getEarlyBeanRefrence(beanName,mbd,bean);
    4     }
    5 });

    具体步骤分析:
    spring容器创建“testA”bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”,用于返回一个提前暴露一个创建中的bean,并将“testA”标识符
    当到“当前创建bean池”,然后进行setter注入“testB”

    spring容器创建“testB”bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”,用于返回一个提前暴露一个创建中的bean,并将“testB”标识符
    当到“当前创建bean池”,然后进行setter注入“circle”

    spring容器创建“testC”bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”,用于返回一个提前暴露一个创建中的bean,并将“testC”标识符
    当到“当前创建bean池”,然后进行setter注入“testA”,进行注入“testA”时由于提前暴露了“ObjectFactory”工厂,从而使它返回提前暴露一个创建中的bean

    最后在依赖注入“testA”和“testB”,完成依赖注入

    (3)protoType范围的依赖处理
    对于“protoType”作用域bean,spring容器无法完成依赖注入,因为spring容器不进行缓存“protoType”作用域的bean,因此无法暴露一个创建中的bean
    对于“singleston”作用域的bean,可以通过“setAllowCircularReferences(false)”来禁用循环引用

  • 相关阅读:
    avalon ms-repeat avalon1
    抓取各个浏览器引擎关键字,,百度学术关键字
    JS中Float类型加减乘除 修复
    js jquery 权限单选 bug修改以及正确代码 购物车数量加减
    图片加载错误默认显示图片
    文本框中焦点竖杆长度控制
    Go语言中 Print,Println 和 Printf 的区别(八)
    typescript中新增的基本数据类型
    尝试自己搭一个简单的typescript运行环境
    Go语言流程控制中的break,continue和goto(七)
  • 原文地址:https://www.cnblogs.com/ssh-html/p/11218057.html
Copyright © 2011-2022 走看看