11 张流程图帮你搞定 Spring Bean 生命周期 (核心)
在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近吧整个流程化成了一个流程图。待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程。注意因为代码比较多,这里的流程图只画出了大概的流程,具体的可以深入代码Java面试宝典完整版PDF
1.获取Bean
第一阶段获取Bean
这里的流程图的入口在AbstractBeanFactory
类的doGetBean
方法。主要流程就是
- 先处理Bean 的名称,因为如果以“&”开头的Bean名称表示获取的是对应的FactoryBean对象;
- 从缓存中获取单例Bean,有则进一步判断这个Bean是不是在创建中,如果是的就等待创建完毕,否则直接返回这个Bean对象
- 如果不存在单例Bean缓存,则先进行循环依赖的解析
- 解析完毕之后先获取父类BeanFactory,获取到了则调用父类的getBean方法,不存在则先合并然后创建Bean
2.创建Bean
2.1 创建Bean之前
在真正创建Bean之前逻辑
这个流程图对应的代码在AbstractAutowireCapableBeanFactory
类的createBean
方法中。
-
这里会先获取
RootBeanDefinition
对象中的Class对象并确保已经关联了要创建的Bean的Class。 -
这里会检查3个条件
(1)Bean的属性中的beforeInstantiationResolved
字段是否为true,默认是false。
(2)Bean是原生的Bean
(3)Bean的hasInstantiationAwareBeanPostProcessors
属性为true,这个属性在Spring准备刷新容器钱转杯BeanPostProcessors的时候会设置,如果当前Bean实现了InstantiationAwareBeanPostProcessor
则这个就会是true。
当三个条件都存在的时候,就会调用实现的InstantiationAwareBeanPostProcessor
接口的postProcessBeforeInstantiation
方法,然后获取返回的Bean,如果返回的Bean不是null还会调用实现的BeanPostProcessor
接口的postProcessAfterInitialization
方法,这里用代码说明protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; //条件1 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { //条件2跟条件3 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { //调用实现的postProcessBeforeInstantiation方法 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { //调用实现的postProcessAfterInitialization方法 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } //不满足2或者3的时候就会设置为false mbd.beforeInstantiationResolved = (bean != null); } return bean; }
-
如果上面3个条件其中一个不满足就不会调用实现的方法。默认这里都不会调用的这些
BeanPostProcessors
的实现方法。然后继续执行后面的doCreateBean
方法。
2.1 真正的创建Bean,doCreateBean
doCreateBean方法逻辑
这个代码的实现还是在AbstractAutowireCapableBeanFactory
方法中。流程是
- 先检查
instanceWrapper
变量是不是null,这里一般是null,除非当前正在创建的Bean在factoryBeanInstanceCache
中存在这个是保存还没创建完成的FactoryBean的集合。 - 调用createBeanInstance方法实例化Bean,这个方法在后面会讲解
- 如果当前
RootBeanDefinition
对象还没有调用过实现了的MergedBeanDefinitionPostProcessor
接口的方法,则会进行调用 - 当满足以下三点
(1)是单例Bean
(2)尝试解析bean之间的循环引用
(3)bean目前正在创建中
则会进一步检查是否实现了SmartInstantiationAwareBeanPostProcessor
接口如果实现了则调用是实现的getEarlyBeanReference
方法 - 调用
populateBean
方法进行属性填充,这里后面会讲解 - 调用
initializeBean
方法对Bean进行初始化,这里后面会讲解
2.1.1 实例化Bean,createBeanInstance
实例化Bean
这里的逻辑稍微有一点复杂,这个流程图已经是简化过后的了。简要根据代码说明一下流程
- 先检查Class是否已经关联了,并且对应的修饰符是否是public的
- 如果用户定义了Bean实例化的函数,则调用并返回
- 如果当前Bean实现了
FactoryBean
接口则调用对应的FactoryBean
接口的getObject
方法 - 根据getBean时候是否传入构造参数进行处理
4.1 如果没有传入构造参数,则检查是否存在已经缓存的无参构造器,有则使用构造器直接创建,没有就会调用instantiateBean
方法先获取实例化的策略默认是CglibSubclassingInstantiationStrategy
,然后实例化Bean。最后返回
4.2 如果传入了构造参数,则会先检查是否实现了SmartInstantiationAwareBeanPostProcessor
接口,如果实现了会调用determineCandidateConstructors
获取返回的候选构造器。
4.3 检查4个条件是否满足一个
(1)构造器不为null,
(2)从RootBeanDefinition中获取到的关联的注入方式是构造器注入(没有构造参数就是setter注入,有则是构造器注入)
(3)含有构造参数
(4)getBean方法传入构造参数不是空
满足其中一个则会调用返回的候选构造器实例化Bean并返回,如果都不满足,则会根据构造参数选则合适的有参构造器然后实例化Bean并返回 - 如果上面都没有合适的构造器,则直接使用无参构造器创建并返回Bean。
2.1.2 填充Bean,populateBean
填充Bean
这里还是根据代码来说一下流程
- 检查当前Bean是否实现了
InstantiationAwareBeanPostProcessor
的postProcessAfterInstantiation
方法则调用,并结束Bean的填充。 - 将按照类型跟按照名称注入的Bean分开,如果注入的Bean还没有实例化的这里会实例化,然后放到
PropertyValues
对象中。 - 如果实现了
InstantiationAwareBeanPostProcessor
类的postProcessProperties
则调用这个方法并获取返回值,如果返回值是null,则有可能是实现了过期的postProcessPropertyValues
方法,这里需要进一步调用postProcessPropertyValues
方法 - 进行参数填充
2.1.3 初始化Bean,initializeBean
初始化Bean
同时这里根据代码跟流程图来说明
-
如果Bean实现了
BeanNameAware
,BeanClassLoaderAware
,BeanFactoryAware
则调用对应实现的方法 -
Bean不为null并且bean不是合成的,如果实现了
BeanPostProcessor
的postProcessBeforeInitialization
则会调用实现的postProcessBeforeInitialization
方法。在ApplicationContextAwareProcessor
类中实现了postProcessBeforeInitialization
方法。而这个类会在Spring刷新容器准备beanFactory
的时候会加进去,这里就会被调用,而调用里面会检查Bean是不是EnvironmentAware
,EmbeddedValueResolverAware
,ResourceLoaderAware
,ApplicationEventPublisherAware
,MessageSourceAware
,ApplicationContextAware
的实现类。这里就会调用对应的实现方法。代码如下 -
实例化Bean然后,检查是否实现了
InitializingBean
的afterPropertiesSet
方法,如果实现了就会调用 -
Bean不为null并且bean不是合成的,如果实现了
BeanPostProcessor
的postProcessBeforeInitialization
则会调用实现的postProcessAfterInitialization
方法。
到此创建Bean 的流程就没了,剩下的就是容器销毁的时候的了
3.destory方法跟销毁Bean
Bean在创建完毕之后会检查用户是否指定了destroyMethodName
以及是否实现了DestructionAwareBeanPostProcessor
接口的requiresDestruction
方法,如果指定了会记录下来保存在DisposableBeanAdapter
对象中并保存在bean的disposableBeans
属性中。代码在AbstractBeanFactory
的registerDisposableBeanIfNecessary
中
在销毁Bean的时候最后都会调用AbstractAutowireCapableBeanFactory
的destroyBean
方法。
这里是创建一个DisposableBeanAdapter
对象,这个对象实现了Runnable接口,在实现的run
方法中会调用实现的DisposableBean
接口的destroy
方法。并且在创建DisposableBeanAdapter
对象的时候会根据传入的bean是否实现了DisposableBean
接口来设置invokeDisposableBean
变量,这个变量表实有没有实现DisposableBean
接口
4.总结。
最后来一个大的流程
实例化前的准备阶段
实例化前
实例化后
初始化前Java面试宝典完整版PDF
初始化之后+销毁