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)”来禁用循环引用

posted @ 2019-07-20 16:02  ssc在路上  阅读(2191)  评论(0编辑  收藏  举报