从BeanFactory源码看Bean的生命周期
下图是我搜索“Spring Bean生命周期”找到的图片,来自文章——Spring Bean的生命周期
下面,我们从AbstractAutowireCapableBeanFactory
的源码中来分析这张图的各个阶段到底是怎么执行的。BeanFactory的基本源码解读在Spring BeanFactory接口分析&源码解读这篇文章中,如果读本篇文章稍显吃力,可以先去看看上面那篇。
我们所用到的BeanFactory,ApplicationContext基本都继承了
AbstractAutowireCapableBeanFactory
,它是一个具有自动装载能力的BeanFactory,它可以响应@Autowire
注解,所以,单独分析这个类不是没用的,而且很有必要。同时,由于Spring的BeanFactory层次结构中大量的使用了模板模式,所以我们可能在这个类的父子类中跳入跳出。
Bean生命周期简单描述#
我们先不看那些繁杂的生命周期方法回调,只看核心的部分,也就是图中四个大的黄色块
- 根据BeanDefinition创建Bean,这个过程称为实例化
- 填充Bean的属性
- 这时,Bean已经创建完毕并可以投入使用,这时需要调用Bean的初始化方法(如果用户指定了的话),这个过程称为初始化
- Bean被销毁
所以,可以将Bean的创建归纳为:
- 实例化
- 设置属性
- 初始化
- 销毁
虽然上面我们把大部分的繁杂的生命周期Hook给屏蔽了,总结出了四个核心的过程,但是这些Hook给了Spring框架带来了无尽的灵活性,所以也是非常重要的。但它们太容易让人眼花了,所以在继续之前,我们有必要先介绍一下那些东西都是什么,是用来解决什么问题的。
BeanPostProcessor接口#
BeanPostProcessor接口有如下方法:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
从方法名上看,xxxxBeforeInitialization
,xxxAfterInitialization
,意思是在初始化阶段前后做一些事,它的参数中,有实际创建出来的Bean和Bean的名字,该方法默认情况下返回原始的bean,也可以返回该bean的某种代理,实际上AOP就是通过这个接口来实现bean代理的返回的。
所以,BeanPostProcessor
实际关心的是Bean的初始化阶段。
ConfigurableBeanFactory
接口的addBeanPostProcessor
方法可以向BeanFactory中注册BeanPostProcessor
InstantiationAwareBeanPostProcessor#
首先,它继承BeanPostProcessor
,所以它是一个BeanPostProcessor
。但是从名字来看,InstantiationAware
表示它更关心对于Bean的实例化阶段的感知,而不是初始化阶段,它发生在初始化阶段前面。
它的方法如下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
// 省略一个过时方法...
}
首先,xxxBeforeInstantiation
、xxxAfterInstantiation
是很容易和之前的两个搞混的,不过以Instantiation
结尾代表着它们关心的是Bean实例化的前后,在实例化前,该方法同样允许返回一个代替该Bean的对象,不过这次由于Bean还没有实际创建出来,所以它的参数中没有Bean对象,而是该Bean的Class对象。而在实例化后,它允许返回一个布尔值来指定是否该对该Bean的属性进行设置(true设置,false跳过)。
Aware生命周期感知接口#
Aware接口里啥也没有,有方法的是它的子接口
public interface Aware { }
Aware被一个想要感知到框架中的某种信息的Bean实现,比如一个Bean可能对创建它的Bean工厂感兴趣,那么它可以实现这个接口:
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
Bean工厂会在该Bean的初始化阶段检测该Bean是否实现了这个接口,如果实现了就调用它的setBeanFactory
方法将工厂设置进去。
请注意,Aware被Bean实现,作用于单个Bean,BeanPostProcessor被注册到Bean工厂中,作用于工厂中的每个Bean。
实例化Bean&属性设置#
这图里所描述的是,创建Bean时先从BeanDefinition开始,然后实例化Bean,在实例化前后,InstantiationAwareBeanPostProcessor
会被调用。
下面从doGetBean
方法开始(getBean
方法实际调用的方法,它已经是AbstractBeanFactory
中的方法了),看下面的代码需要注意,Spring中Bean的作用域可以分为Singleton、Prototype和其它,其中Singleton和Prototype是Spring框架原生支持的,其它作用域需要自行扩展,比如SpringWebMVC扩展了Session等作用域。所以你看下面的代码时也要在脑袋里把它们分成Singleton、Prototype和其它作用域,要不然你可能就被这很长很长的代码搞迷糊了:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// ...
try {
// 根据BeanName获取BeanDefinition
// MergedBeanDefinition是将它和它的祖先Bean整合,这里可以先忽略,就当作普通的BeanDefinition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 如果是Singleton,按Singleton的方法创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// [+] 实际创建Bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是Prototype,按Prototype的方法创建
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// [+] 实际创建Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 如果是其它作用域,那么就放到其它作用域中创建
// 这里的逻辑和Singleton很像,在Singleton创建中
// Bean放到SingletonBeanRegistry中管理,而这个
// 放到对应的作用域中管理
else {
String scopeName = mbd.getScope();
Scope scope = this.scopes.get(scopeName);
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
// [+] 实际创建Bean
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {}
}
}
catch (BeansException ex) {}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
所以,不管是哪个作用域,它们都调用了createBean
来创建Bean,AbstractBeanFactory
中并没有实现这个方法,createBean
是AbstractAutowireCapableBeanFactory
抽象类实现的:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
try {
// 在Bean实例化之前,让一些关心实例化阶段的BeanPostProcessor得到执行
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果返回的bean不是null,那么结束整个阶段,直接返回这个值作为bean
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {}
try {
// 实例化Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {}
catch (Throwable ex) {}
}
所以,resolveBeforeInstantiation
方法应该就是查找那些InstantiationAwareBeanPostProcessor
,然后调用它们。
InstantiationAwareBeanPostProcessor的before hook#
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 应用BeanPostProcessor的beforeInstantiation
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 调用BeanPostProcessors的初始化后方法,注意是初始化后不是实例化后
// 前提是before方法返回了一个对象
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
我们可以看到,这个方法的代码非常简单,虽然还没写明,但是99%就是调用所有的InstantiationAwareBeanPostProcessor
了,两个apply
应该就是做这个工作的。我们不妨点进去看一个:
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
}
这不就是对所有的InstantiationAwareBeanPostProcessor
进行遍历调用吗,取第一个返回结果的Processor的结果。大家说,这里用到了什么设计模式??
InstantiationAwareBeanPostProcessor before hook的使用#
下面,我们自己创建一个实现类,它的功能就是打印所有进来的Bean名字和类型:
public class MyInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("[+] > MyInstantiationProcessor before bean instantiation : " + beanName + " => " + beanClass.getName());
return null;
}
}
下面,我们把它设置到BeanFactory中,然后尝试获取Bean:
factory.addBeanPostProcessor(new MyInstantiationProcessor());
Workbench workbench = factory.getBean(Workbench.class);
System.out.println(workbench);
输出:
[+] > MyInstantiationProcessor before bean instantiation : workbench => top.yudoge.springserials.basic.beanfactory.beans.Workbench
[+] > MyInstantiationProcessor before bean instantiation : person => top.yudoge.springserials.basic.beanfactory.beans.Person
Workbench(operator=Person(name=Yudoge))
因为Workbench
对象依赖Person
对象,所以引起了两个对象的连锁创建,最后一行我们得到了Workbench
对象。
下面我们尝试让BeanPostProcessor针对Person类返回一个另外的Bean,而不是null
:
public class MyInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("[+] > MyInstantiationProcessor before bean instantiation : " + beanName + " => " + beanClass.getName());
if (beanClass.getName().equals(Person.class.getName())) {
return new Person("我是MyInstantiationProcessor返回的Person");
}
return null;
}
}
运行:
[+] > MyInstantiationProcessor before bean instantiation : workbench => top.yudoge.springserials.basic.beanfactory.beans.Workbench
[+] > MyInstantiationProcessor before bean instantiation : person => top.yudoge.springserials.basic.beanfactory.beans.Person
Workbench(operator=Person(name=我是MyInstantiationProcessor返回的Person))
成功的返回了我们创建出来的Person。
对目前的InstantiationAwareBeanPostProcessor
的before阶段做一个总结:
- BeanFactory会在创建Bean之前调用所有这种Processor的before方法
- 如果在before中返回了一个对象,那么这个对象就会代替原来的Bean,并且该bean的初始化后(不是实例化后)方法会被立即调用
- 否则,就是before中返回null,这时进入正常的Bean创建流程
这个总结只是
AbstractAutowireCapableBeanFactory
中的实现方式,是否有其它BeanFactory以其它方式实现,暂不明确
实际实例化Bean#
所以,当InstantiationAwareBeanPostProcessor
没有返回一个替代对象时,进入正常的Bean创建流程,开始实例化Bean。
回到AbstractAutowireBeanFactory
的createBean
方法:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
try {
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) { }
try {
// 创建Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {}
}
这个doCreateBean
方法就是用来实际实例化Bean的:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
// 如果是Singleton,从缓存中拿原来的Bean
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 实例化Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 从BeanWrapper中拿出实际的Bean对象
Object bean = instanceWrapper.getWrappedInstance();
// ...
}
向populateBean方法中试探——InstantiationAwareBeanPostProcessor的after方法#
doCreateBean
方法里有这样两行:
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
很明显,它们代表了Bean生命周期的属性设置阶段和初始化阶段,但是到目前为止,我们还没有看到InstantiationAwareBeanPostProcessor
的除了before
以外的另两个方法被调用。虽然populateBean
方法名看起来就是设置Bean属性了,但我们也只能往下看,没准InstantiationAwareBeanPostProcessor
的另外两个方法在这个populateBean
设置属性之前被调用了呢?
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 调用所有InstantiationAwareBeanPostProcessor的BeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
// ...
}
我日尼玛,果然啊!!!进来就开始调用InstantiationAwareBeanPostProcessor
的after方法
所以,做个小总结:
- 对于那些
InstantiationAwareBeanPostProcessor
没有拦截(before实例化方法返回null的)的Bean,InstantiationAwareBeanPostProcessor
的after实例化方法也会被调用 - 而对于那些before实例化方法没有返回null的,这个after实例化方法不会走,直接调用了after初始化方法,也就是说把实例化到初始化中间的过程都跳过了
InstantiationAwareBeanPostProcessor的postProcessProperties方法#
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 调用after实例化方法
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
// 获取所有属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 自动注入,自动注入是针对pvs的,而不是bean本身
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 对于所有的InstantiationAwareBeanPostProcessor,调用它们的属性设置方法
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 对于所有InstantiationAwareBeanPostProcessor,调用它的postProcessProperties方法
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
// 如果该方法返回的新pvs为null,那么再调用postProcessPropertyValues
if (pvsToUse == null) {
// 该方法默认返回初始pvs
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
// 让pvs等于两次BeanProcessor方法调用后返回的pvs
pvs = pvsToUse;
}
}
// 实际设置Bean属性
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
在这里,我们可以看到,BeanFactory并没有实际设置属性,而是先用一个pvs数据结构来保存所有待设置的属性,自动注入时也操作的是pvs。这给了InstantiationAwareBeanPostProcessor
可以对属性值进行二次修改的能力。
InstantiationAwareBeanPostProcessor
的两个与属性相关的方法都可以返回新的pvs,你可以对原始pvs进行改动。而postProcessProperties
方法默认返回null
,就是不改动,postProcessPropertyValues
方法默认返回原始pvs,也是不改动。
稍后,BeanFactory会把pvs应用到Bean中。
postProcessProperties方法的实战#
这里,我们检测如果pvs中有名为operator
的属性要设置,我们就创建一个新的pvs,并覆盖它的operator
属性,并返回它,否则我们返回null,也就是不覆盖属性:
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (pvs.contains("operator")) {
MutablePropertyValues clonedPvs = new MutablePropertyValues(pvs);
clonedPvs.addPropertyValue("operator", new Person("修改了pvs之后的person"));
return clonedPvs;
}
return null;
}
结果,由于autowire阶段Person已经被创建了,所以结果中person的实例化阶段也被打印了:
[+] > MyInstantiationProcessor before bean instantiation : workbench => top.yudoge.springserials.basic.beanfactory.beans.Workbench
[+] > MyInstantiationProcessor before bean instantiation : person => top.yudoge.springserials.basic.beanfactory.beans.Person
Workbench(operator=Person(name=修改了pvs之后的person))
由于我不了解直接修改原始pvs会不会有副作用,所以我选择了克隆一个对象
这两个阶段最后的总结#
回到这个图上
- 从BeanDefinition创建实例化Bean
- 实例化之前如果有
InstantiationAwareBeanPostProcessor
,调用before实例化方法 - 如果并没有一个实例化BeanPostProcessor接管Bean创建,那么进入正常实例化阶段
- 实例化Bean
- 调用
InstantiationAwareBeanPostProcessor
的after实例化方法 - 对pvs进行设置
- 调用
InstantiationAwareBeanPostProcessor
的postProcessProperties方法对pvs进行修改 - 实际的Bean属性设置
初始化阶段#
看起来挺复杂的,其实很简单:
主要分为几个阶段:
- Aware接口的回调
- BeanPostProcessor的before初始化回调
- 各种初始化方法的回调
- BeanPostProcessor的after初始化回调
所以,初始化阶段其实没做任何实际的事,只是对各种生命周期方法和Bean感知方法进行回调,通知它们Bean已经初始化了。或者也可以理解为,初始化阶段做的最主要的工作就是调用Bean的aware感知方法和初始化方法
// doCreateBean
// 属性设置阶段
populateBean(beanName, mbd, instanceWrapper);
// 初始化阶段
exposedObject = initializeBean(beanName, exposedObject, mbd);
进入initalizeBean
,可以看到里面的代码正对应着图中的每一步:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 调用感知方法
invokeAwareMethods(beanName, bean);
// 调用BeanPostProcessor的before初始化方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 调用自定义初始化方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
// 调用BeanPostProcessor的after初始化方法
catch (Throwable ex) {}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Aware感知方法的调用#
进入invokeAwareMethod
方法,里面对BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
做了检测,并调用了对应的设置方法:
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
对于BeanFactory,它只支持这些Aware,ApplicationContext会支持更多的Aware。
Aware感知方法的实战#
让Workbench
类实现BeanFactoryAware
接口并打印出创建它的BeanFactory:
@Data
public class Workbench implements BeanFactoryAware {
@Autowired
private Person operator;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactory => " + beanFactory);
}
}
需要注意的是,一旦你的Bean实现了某个Aware接口,就证明它要感知到某些框架中的东西,这会让它直接与框架产生耦合。
BeanPostProcessor before初始化的调用#
这里和之前的套路一样,并且before
方法可以返回一个包装过的Bean做为代理(默认不包装,这时wrappedBean==bean)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
invokeAwareMethods(beanName, bean);
// 进行before初始化调用
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// ...
}
遍历每个BeanPostProcessor,调用before初始化方法:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
没啥好解释的,实际上InstantiationAwareBeanPostProcessor
的过程和它差不多,并且比它复杂。
init-method的调用#
// 调用before初始化
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用init-method
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
那么我们来查看invokeInitMethods
方法:
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 该Bean是否是initializingBean的实例
boolean isInitializingBean = (bean instanceof InitializingBean);
// 如果是,并且有`afterPropertiesSet`方法
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
// 调用afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();
}
if (mbd != null && bean.getClass() != NullBean.class) {
// 获取init-method名字
String initMethodName = mbd.getInitMethodName();
// 如果`initMethodName`不是空并且`initMethodName`并不和`afterPropertiesSet`同名且不是InitalizingBean(防止重复调用),并且Bean中实际有这个方法
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
// 调用initmethod
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
所以,BeanFactory先是对于实现了InitializingBean
的Bean的afterPropertiesSet
进行调用,然后再对用户指定的init-method
进行调用。
InitializingBean实战#
@Data
public class Workbench implements InitializingBean {
@Autowired
private Person operator;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
}
结果:
afterPropertiesSet
Workbench(operator=Person(name=Yudoge))
init-method实战#
添加init
方法
@Data
public class Workbench implements InitializingBean {
@Autowired
private Person operator;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
public void init() {
System.out.println("init");
}
}
向BeanDefinition
中设置init方法名
// 设置Init方法名
workbenchRbd.setInitMethodName("init");
结果
afterPropertiesSet
init
Workbench(operator=Person(name=Yudoge))
关于@PostConstruct#
貌似BeanFactory并不支持@PostConstruct
,它好像是ApplicationContext通过预注册InstantiationAwareBeanPostProcessor
实现的。这是我猜的。
BeanPostProcessor.post初始化#
略,因为前面已经讲了够多了,猜也能猜到怎么实现的
初始化阶段总结#
- 调用Aware方法
- 调用BeanPostProcessor的before初始化
- 如果是InitializingBean,调用afterPropertiesSet方法
- 如果有
init-method
,调用 - 调用BeanPostProcessor的after初始化
尾声:Bean的销毁阶段#
回到doCreateBean
方法中,最后,该方法判断了,如果必要的话就将该Bean注册到DisposableBean中:
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {}
我猜其中的逻辑就是看看该Bean是不是DisposableBean
的实例,如果是,注册到一个什么表中,方便销毁Bean时调用它的destory
方法。
我们先不管,先看BeanFactory中有没有什么destroyBean
这种方法。果然,在ConfigurableBeanFactory
中定义了这个方法,AbstractBeanFactory
把它实现了:
@Override
public void destroyBean(String beanName, Object beanInstance) {
destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
}
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy();
}
这里创建了一个什么DisposableBeanAdapter
,然后调用了destroy
方法,就没干别的了。
DisposableBeanAdapter#
DisposableBeanAdapter
的描述如下:
/**
* 实现了`DisposableBean`和`Runnable`的Adapter,对给定的Bean执行多个销毁步骤:
*
* - DestructionAwareBeanPostProcessors;
* - 本身就实现了DisposableBean的Bean
* - BeanDefinition中定义的Bean销毁方法
*/
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable
所以,看起来,整个Bean的销毁步骤都是这哥们儿一个人完成的喽。
不过这个图应该画错了,它把DestructionAwareBeanPostProcessors
写成了InstantiationAwareBeanPostProcessor
。
看看它被调用的构造方法里写了啥:
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
this.bean = bean;
this.beanName = beanName;
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
// 该Bean是不是可调用的DisposableBean
this.invokeDisposableBean = (bean instanceof DisposableBean &&
!beanDefinition.hasAnyExternallyManagedDestroyMethod(DESTROY_METHOD_NAME));
// destroy方法名
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
// 和初始化哪里一样,防止destroy方法名和DisposableBean的方法名一样,重复调用
if (destroyMethodName != null &&
!(this.invokeDisposableBean && DESTROY_METHOD_NAME.equals(destroyMethodName)) &&
!beanDefinition.hasAnyExternallyManagedDestroyMethod(destroyMethodName)) {
// 如果Bean是一个AutoClosable并且自定义的销毁方法名也是close的话
this.invokeAutoCloseable = (bean instanceof AutoCloseable && CLOSE_METHOD_NAME.equals(destroyMethodName));
if (!this.invokeAutoCloseable) {
// 如果不是,destroyMethodName就使用用户指定的并解析对应方法
this.destroyMethodName = destroyMethodName;
Method destroyMethod = determineDestroyMethod(destroyMethodName);
// 省略一些destroy method参数设置相关的代码
this.destroyMethod = destroyMethod;
}
}
// 获取beanPostProcessors(filterPostProcessors会过滤掉所有非DestructionAwareBeanPostProcessor的类)
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
this.acc = acc;
}
这里就是做了一些初始化工作,把需要的成员变量都解析出来,方便后面destroy
时使用。
然后我们看看destroy
方法:
public void destroy() {
// 调用所有DestructionAwareBeanPostProcessor的postProcessBeforeDestruction
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
// 如果是一个disposableBean,调用它的destroy
if (this.invokeDisposableBean) {
((DisposableBean) this.bean).destroy();
}
// 如果是AutoCloseable(并且自定义销毁方法名也是close),直接调用close
if (this.invokeAutoCloseable) {
((AutoCloseable) this.bean).close();
}
// 否则去调用自定义方法
else if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
// 有可能存在destroyMethod没解析,但是destroyMethodName有了的情况,解析并调用
else if (this.destroyMethodName != null) {
Method destroyMethod = determineDestroyMethod(this.destroyMethodName);
if (destroyMethod != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(destroyMethod, this.bean.getClass()));
}
}
}
实战DestructionAwareBeanPostProcessor#
创建DestructionAwareBeanPostProcessor
public class MyDestructionProcessor implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println("[+] DestructionProcessor : " + beanName);
}
}
向工厂中添加BeanPostProcessor
,并销毁Bean:
factory.addBeanPostProcessor(new MyDestructionProcessor());
factory.destroyBean("workbench", workbench);
结果:
Workbench(operator=Person(name=Yudoge))
[+] DestructionProcessor : top.yudoge.springserials.basic.beanfactory.beans.Workbench
实战DisposableBean#
让Bean实现DisposableBean
@Data
public class Workbench implements DisposableBean {
@Autowired
private Person operator;
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy");
}
}
结果:
Workbench(operator=Person(name=Yudoge))
[+] DestructionProcessor : top.yudoge.springserials.basic.beanfactory.beans.Workbench
DisposableBean destroy
实战CustomDestroyMethod#
添加自定义销毁方法
@Data
public class Workbench implements DisposableBean {
@Autowired
private Person operator;
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy");
}
public void customDestroyMethod() {
System.out.println("Custom destroy method...");
}
}
在BeanDefinition中定义:
workbenchRbd.setDestroyMethodName("customDestroyMethod");
结果:
Workbench(operator=Person(name=Yudoge))
[+] DestructionProcessor : workbench
DisposableBean destroy
Custom destroy method...
总结#
现在,Bean销毁阶段的逻辑已经全部理解完毕
- 调用DestructionAwareBeanPostProcessor的before销毁方法
- 如果实现了DisposableBean,调用它的Destroy方法
- 调用自定义destroy-method方法
- 说明:真正意义上的销毁(从容器中移除bean)是在AbstractApplicationContext.close方法中实现的,在此方法中不仅会将bean从容器中移除,还会调用到我们实现的这些回调相关的方法。
最后的总结#
- 从BeanDefinition获取Bean信息
- 调用
InstantiationAwareBeanPostProcessor
的before实例化方法 - 如果它返回一个对象,那么直接进入该对象的初始化后方法
- 否则,它返回null,进入正常的Bean生命周期
- 实例化Bean
- 调用
populateBean
,该方法的目的是对Bean属性进行设置 - 调用
InstantiationAwareBeanPostProcessor
的after实例化方法,该方法的返回值决定是否跳过属性设置阶段 - 解析该Bean的pvs,自动注入该pvs
- 调用
InstantiationAwareBeanPostProcessor
中两个和属性设置有关的方法,允许它们对属性进行动态修改 - 调用
initializingBean
进入初始化阶段 - 检测Bean实现了哪些Aware接口,调用它们
- 调用所有
BeanPostProcessor
的before初始化方法,该方法可以返回Bean的一个代理 - 如果Bean是
InitializingBean
,调用它的afterPropertiesSet
方法 - 如果Bean设置了启动方法,调用启动方法
- 调用所有
BeanPostProcessor
的after初始化方法,该方法可以返回Bean的一个代理 - 调用
destroyBean
进入Bean销毁阶段 - 创建
DisposableBeanAdapter
,它负责对Bean的销毁进行生命周期方法的调用 - 调用所有
DestructionAwareBeanPostProcessor
的before销毁方法 - 如果是
DisposableBean
,调用destroy
方法 - 如果设置了
destroy-method
,调用它
参考原文链接:https://www.cnblogs.com/lilpig/p/16477006.html
从BeanFactory源码看Bean的生命周期的更多相关文章
- 【学习笔记】Spring中的BeanFactory和ApplicationContext 以及 Bean的生命周期(Y2-3-2)
BeanFactory和ApplicationContext Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类. Spring提供了两种不同的容器: 一种是最基本的Bean ...
- spring BeanFactory及ApplicationContext中Bean的生命周期
spring bean 的生命周期 spring BeanFactory及ApplicationContext在读取配置文件后.实例化bean前后.设置bean的属性前后这些点都可以通过实现接口添加我 ...
- Vue源码之组件化/生命周期(个人向)
大致流程 具体流程 组件化 (createComponent) 构造⼦类构造函数 const baseCtor = context.$options._base // plain options ob ...
- 一起学习vue源码 - Vue2.x的生命周期(初始化阶段)
作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...
- React源码剖析系列 - 生命周期的管理艺术
目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理.本系列文章希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. 对于 React,其组件生命周期(C ...
- React 源码剖析系列 - 生命周期的管理艺术
目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理. 本系列文章 希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. 对于 React,其组件生命周期 ...
- SuperSocket源码解析之会话生命周期
一 基本概念 会话(Session)是客户端与服务器进行通信的基本单元,也是一个Socket的封装,在http协议中也有Session机制,其主要作用封装一个通信单元socket,负责服务器与客户端消 ...
- Vue源码之 Vue的生命周期
天地初开就是new Vue(options),里面就一句话 this._init(options); (Vue.prototype.init 的赋值在initMixin(Vue)方法里) _init方 ...
- JAVA面试题:Spring中bean的生命周期
Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...
随机推荐
- 轻松月薪过万,NISP证书含金量有多重|NISP管理中心|网安伴|nisp
nisp一级证书含金量 NISP一级证书是面向各个行业工作人员信息安全意识普及化和网络信息安全基础培训的国家级验证.持NISP一级证书可以从信息安全保密较高的单位得到加分.证书由中国信息安全测评中心授 ...
- flutter系列之:UI layout简介
目录 简介 flutter中layout的分类 常用layout举例 总结 简介 对于一个前端框架来说,除了各个组件之外,最重要的就是将这些组件进行连接的布局了.布局的英文名叫做layout,就是用来 ...
- (数据科学学习手札141)利用Learn Git Branching轻松学习git常用操作
1 简介 大家好我是费老师,Git作为世界上最流行的版本控制系统,可以说是每一位与程序打交道的朋友最值得学习的软件之一.除了管理自己的项目,如果你对参与开源项目感兴趣,那么Git更是联结Github. ...
- 3.Ceph 基础篇 - RBD 块存储使用
文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247485253&idx=1&sn=24d9b06a ...
- 修改 Docker容器 自动启动/不自动启动,挂载路径,存储位置
有时候创建容器时忘了添加参数 --restart=always,当 Docker 重启时,容器未能自动启动, 现在要添加该参数怎么办呢,方法有二: 1.Docker 命令修改 docker conta ...
- 使用Kuboard界面在k8s上部署SpringCloud项目
先安装Ingress Controller 安装Ingress Controller后,其他服务设置Ingress后就可以通过设置的域名进行访问了,就不用通过代理的方式或者ip:port的方式进行访问 ...
- rpm,docker,k8s三种方式安装部署GitLab服务
rpm方式 源地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ wget https://mirrors.tuna.tsinghua ...
- 5_SpringMVC
一. 什么是MVC框架 MVC全名是Model View Controller, 是模型(model), 视图(view), 控制器(controller)的缩写, 一种软件设计典范, 用一种业务逻辑 ...
- PAT (Basic Level) Practice 1027 打印沙漏 分数 20
本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个"*",要求按下列格式打印 ***** *** * *** ***** 所谓"沙漏形状",是指 ...
- aardio + PowerShell 可视化快速开发独立 EXE 桌面程序
aardio 可以方便地调用 PowerShell ,PowerShell 中也可以自由调用 aardio 对象与函数.不用带上体积很大的System.Management.Automation.dl ...