前言
- 上篇博客spring 5.0.x源码学习系列七: 后置处理器ConfigurationClassPostProcessor之BeanFactoryPostProcessor身份次要介绍了ConfigurationClassPostProcessor的BeanFactoryPostProcessor身份。接下来,将进入spring最外围的
bean实例化
过程。
一、解析构建bean过程
- 构建bean的过程太简单,将依据我本人写的流程图来一一解说
1.1 流程图
1.2 流程图解析
1.2.1 创立非形象、单例、非懒加载的bean
整个失常流程是遍历bean工厂寄存beanName的list, 并依据beanName拿到对应的beanDefinition,只过滤掉非形象
、单例
、非懒加载
的beand进行创立
1.2.2 判断以后创立bean的类型并作相应解决
因为spring存在两种bean, 一般bean和FactoryBean,spring在辨别这两种bean的做法是beanName和beanType来双重校验的。假如获取的bean为FactoryBean,那么会在getBean之前在beanName前增加一个&
符号
if (isFactoryBean(beanName)) { // org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX // String FACTORY_BEAN_PREFIX = "&"; Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); // 前面的逻辑省略 }
1.2.3 getBean <=> doGetBean获取bean的通用办法
- 此办法是spring依据beanName获取bean的通用办法。在此办法中有两个中央须要留神:
- 外部会对传入的beanName做解决(将传入的beanName后面的
&
符号去掉并存入外部本人保护的一个变量中), 此时对于以后bean的名称会有两个变量存储,别离是name(办法传入的bean名称), beanName(解决过bean名称) - 不论是从bean工厂的单例池中获取还是新建的bean, 最终都要走
getObjectForBeanInstance
办法来返回bean。这样做次要是为了解决获取的bean类型为FactoryBean的状况。
具体规定可参考此链接:https://github.com/AvengerEug/spring/tree/develop/resourcecode-study#%E5%8D%81%E4%B8%80-%E8%8E%B7%E5%8F%96factorybean%E5%AE%9E%E4%BE%8B%E4%B8%8E%E5%AE%83%E7%BB%B4%E6%8A%A4%E7%9A%84bean%E5%AE%9E%E4%BE%8B%E8%A7%84%E5%88%99
1.2.4 第一次getSingleon
- 此办法很重要
- 失常逻辑(循环bean工厂挨个创立bean)进来, 这里获取的值必定为null
在populateBean主动拆卸须要创立依赖bean时, 这里获取的可能为null也可能不为null. 只有在循环依赖和spring单例池存在bean的状况下, 获取的才不为null, 因为此办法会首先从单例池中获取bean, 若不存在再依据这个bean是否正在被创立从而到"非凡"(依据beanName到singletonFactories拿ObjectFactory, 并依据ObjectFactory获取bean。
public Object getSingleton(String beanName)
1.2.5 第二次调用getSingleton
此办法只有在创立新的bean时才会用到,传入的ObjectFactory是以后类的createBean办法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)
1.2.6 getSingleton外部的beforeSingletonCreation办法
标记bean正在被创立:
此动作很重要, 次要是将beanName寄存至DefaultSingletonBeanRegistry类的singletonsCurrentlyInCreation数据结构(Set<String>), 后续会依据这个根据来解决循环依赖的状况, 即上述1.2.4 第一次getSingleon中所说的获取不为null的状况protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }}
1.2.7 调用传入的createBean办法<=>singletonFactory.getObject()
- 外部会调用至doCreateBean办法
1.2.8 doCreateBean办法
- 外部会创立进去bean, 创立完后还会在此办法中进行主动拆卸populateBean
1.2.9 createBeanInstance办法
此办法为真正创立bean的流程,外部次要做了如下事件
确定以后bean是否通过构造方法主动拆卸, 源码和条件如下:
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); }
1. ctors != null => ctors中存的是构造方法中增加@Autowired注解的情景2. mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR => 此条件为应用后置处理器手动批改beanDefinition的主动拆卸的值, 默认为no3. mbd.hasConstructorArgumentValues() => 应用后置处理器手动增加beanDefinition中寄存构造方法值的情景, eg: mybatis中的definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());4. !ObjectUtils.isEmpty(args)上述条件只有满足一个就走构造方法主动拆卸的逻辑
- 若应用构造方法主动拆卸的论断不成立则走默认构造方法创立bean流程
- 不论是默认构造方法创立bean还是通过构造方法主动拆卸bean,所有bean的创立应用的都是CglibSubclassingInstantiationStrategy策略
1.2.10 确认以后bean是否合乎循环依赖的状况 <=> addSingletonFactory办法
满足循环依赖的三个条件: 单例、allowCircularReferences为true、以后的bean正在创立中
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { // 寄存bean对应的ObjectFactory, 在bean的循环依赖中会用上 this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); // 寄存曾经被注册过的bean this.registeredSingletons.add(beanName); } } }
- 应用构造方法创立bean后, 会做三个操作:
- this.singletonFactories.put(beanName, singletonFactory);
=> 在getBean办法的第一次getSingleton中会用到,其实这个singletonFactory的形参中曾经在创立bean的过程中传入了,并且外部的逻辑是执行SmartInstantiationAwareBeanPostProcessor后置处理器的getEarlyBeanReference办法,此办法能够返回一个bean
)的中央去拿bean - this.earlySingletonObjects.remove(beanName);
- this.registeredSingletons.add(beanName); => 此步骤只是为了记录这个bean曾经被spring创立了或者正在被创立中
所以创立一个bean后(还未依赖注入bean), 会在singletonFactories和registeredSingletons数据结构中都存在相干记录
1.2.11 主动拆卸 <=> populateBean办法
- 此办法中次要是
AutowiredAnnotationBeanPostProcessor
后置处理器来实现主动拆卸,若bean须要主动拆卸,则还须要先实例化依赖的bean,最终又会走到上述getBean逻辑
1.2.12 bean创立结束, 开始执行bean的一些后置处理器
- 调用bean的
BeanPostProcessor
后置处理器postProcessBeforeInitialization办法 - 若bean实现了
InitializingBean
接口, 则调用接口中的办法afterPropertiesSet - 调用bean的
BeanPostProcessor
后置处理器de postProcessAfterInitialization办法
1.2.13 革除bean正在创立的标识并增加至bean工厂
- afterSingletonCreation
// this.singletonsCurrentlyInCreation.remove(beanName) => 移除以后bean name protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } }
- addSingleton
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { // bean工厂单例池 this.singletonObjects.put(beanName, singletonObject); // 执行到这示意以后bean曾经创立实现, 则移除循环依赖的bean的状况, // 若下次还有bean依赖它, 间接从bean工厂的单例池获取即可 this.singletonFactories.remove(beanName); // 以后bean被创立结束,则革除它 this.earlySingletonObjects.remove(beanName); // 再次将bean增加至该汇合中, 该汇合是一个set, 不会反复, 这里反复增加的起因可能是并发状况 this.registeredSingletons.add(beanName); } }
二、一个案例搞清楚循环依赖
2.1 案例背景
- 有两个类: A和B,它们相互依赖(A中要主动拆卸B属性,B中要主动拆卸A属性), 假如先创立A
2.2 流程
- 创立Bean a <=> getBean("a")
第一次调用getSingleton办法, 单例池中无bean a ,也没标识正在被创立, 所以走第二个getSingleton办法。此时a被标注正在被创立走应用构造方法创立bean的逻辑 - 在创立完a后开始记录bean a的一些状态(
将bean name增加至registeredSingletons以及将bean对应的ObjectFactory增加至singletonFactories。即上述的addSingletonFactory办法的操作
)和填充属性, 发现它依赖于B, 此时要去getBean(b) - 而后进入创立bean b流程 <=> getBean("b")
- 此时会进入第一个getSingleton办法, 此时spring单例池中无b并且b也还未被标注为被创立(因为它是在getSingleton办法前面标注的)状态所以进入创立createBean办法
- 同理, 在创立完b后也会记录bean b的一些状态(
将bean name增加至registeredSingletons以及将bean对应的ObjectFactory增加至singletonFactories。即上述的addSingletonFactory办法的操作
) - 创立完b后开始填充属性, 发现它又依赖于A, 此时要去getBean("a")
- 此时进入第一个getSingleton办法,
发现单例池中无a(尽管a在上述过程中被创立了, 然而它还未放入单例池中)然而它是处于被创立的状态, 所以从singletonFactories中依据beanName拿ObjectFactory, 最终从ObjectFactory拿到Bean a
, 并将singletonFactories中beanName对应的objectFactory remove掉,以及将拿到的bean a放入到earlySingletonObjects中 - 最终拿到了bean a, 此时将bean a注入到bean b中的a属性中, 实现bean b的创立(此时会将它正在创立的标识移除并它放入单例池中去), 并调用BeanPostProcessor后置处理器以及InitializingBean接口的afterPropertiesSet办法, 至此bean b的创立完结了 返回bean b。
- 因为上述创立bean b的过程是a要主动拆卸b而执行的, 为的就是获取bean b。当初曾经拿到bean b了, 所以将bean a中的b属性给注入进去, 最终实现bean a的创立, 将a也增加到spring单例池中并调用BeanPostProcessor后置处理器以及InitializingBean接口的afterPropertiesSet办法
- bean a创立实现,循环依赖步骤实现
波及到的几个数据结构:
registeredSingletons
: 示意该bean曾经通过构造方法创立进去了singletonFactories
: 寄存bean对应的objectFactory办法, 循环依赖时须要依据它来拿beanearlySingletonObjects
: 与singletonFactories的操作是互斥的, 外面寄存的是singletonFactories中beanName对应的objectFactory创立进去的bean,若一个beanName在该汇合中存在, 那么该bean对应的ObjectFactory就会在singletonFactories中被remove掉singletonsCurrentlyInCreation
: 示意以后bean正在被创立, 在getSingleton(String beanName, ObjectFactory<?> singletonFactory)办法中进行操作, 增加、移除正在创立的标识都是在此办法中实现
三、spring bean实例化过程中波及到的后置处理器和执行程序
执行程序 | 执行地位 | 执行到的后置处理器 | 执行的办法 | 作用 |
---|---|---|---|---|
1 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.doCreateBean => resolveBeforeInstantiation办法 | InstantiationAwareBeanPostProcessor | 1. postProcessBeforeInstantiation 2.postProcessAfterInitialization | 1. postProcessBeforeInstantiation作用: 若后置处理器中返回了一个对象, 则不会走spring的创立bean的流程 2.若postProcessBeforeInstantiation办法返回的bean不为null则执行postProcessAfterInitialization办法,该办法执行了BeanPostProcessor后置处理器, 主动拆卸的后置处理器就间接实现了BeanPostProcessor, 若BeanPostProcessor不被执行, 那么主动拆卸的性能也将缺失 3. 若bean中实现了aware接口,那么将依照aware的类型诶个执行对应的办法,其中就包含获取spring上下文的ApplicationContextAware |
2 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.createBeanInstance => determineConstructorsFromBeanPostProcessors | SmartInstantiationAwareBeanPostProcessor | determineCandidateConstructors | 扫描以后bean携带@Autowired注解的构造方法或者只有一个带参的构造方法或者等等其余的状况。(具体参考AutowiredAnnotationBeanPostProcessor类的determineCandidateConstructors办法) |
3 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.doCreateBean => applyMergedBeanDefinitionPostProcessors | MergedBeanDefinitionPostProcessor | postProcessMergedBeanDefinition | 将以后类须要主动拆卸的属性全副InjectionMetadata对象中(每个属性对应一个InjectionMetadata对象) |
4 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.doCreateBean => getEarlyBeanReference | SmartInstantiationAwareBeanPostProcessor | getEarlyBeanReference | 当解决循环依赖时,会获取到状态为'正在创立'的bean的援用 |
5 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.populateBean => postProcessAfterInstantiation | InstantiationAwareBeanPostProcessor | postProcessAfterInstantiation | 可能管制以后bean是否持续实现依赖注入逻辑,若办法return false,则以后bean的@Autowired注解性能的依赖注入完结 |
6 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.populateBean => postProcessPropertyValues | InstantiationAwareBeanPostProcessor | postProcessPropertyValues | 解决以后bean主动拆卸的属性 |
7 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.initializeBean => applyBeanPostProcessorsBeforeInitialization | BeanPostProcessor | postProcessBeforeInitialization | 当bean被实例化并实现主动拆卸之后执行 |
8 | org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory.initializeBean => applyBeanPostProcessorsAfterInitialization | BeanPostProcessor | postProcessAfterInitialization | 当bean被实例化并实现主动拆卸之后执行,比postProcessBeforeInitialization办法后执行 |
- 如上, 一共会执行4个后置处理器InstantiationAwareBeanPostProcessor, SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, BeanPostProcessor, 共执行了8次, 其中InstantiationAwareBeanPostProcessor类型的后置处理器调用次数最多, 8次调用中有5次跟它无关, 因为它继承了
BeanPostProcessor
, 并扩大了三个办法postProcessBeforeInstantiation、 postProcessAfterInstantiation和postProcessPropertyValues
四、小结
- 本篇博客还有很多细节未提及,比方spring如何晓得应用哪一个构造方法(假如程序员提供了多个结构器)创立bean、主动拆卸后置处理器AutowiredAnnotationBeanPostProcessor是如何晓得哪些属性须要拆卸哪些不须要、在5个后置处理器的八个中央被调用的具体作用和景点案例也未齐全总结等等。只能等日后再欠缺了
- I am a slow walker, but I never walk backwards.
- github spring源码学习地址: https://github.com/AvengerEug/spring/tree/develop/resourcecode-study