Spring源码学习三——Bean的生命周期主流程

一、实例化

前文讲到容器启动方法refresh()里面,调用finishBeanFactoryInitialization()方法会实例化所有非懒加载的单例bean,bean的生命周期得入口就在这里在这里插入图片描述
前面那些都不重要,进入红框中的方法
在这里插入图片描述
beanNames里面是BeanDefinition的名称,singletonObjects是单例池。比较一下还有一些我们自己创建的类未被实例化
在这里插入图片描述
如果一个bean不是抽象的、是单例的且不是懒加载就会进入if,然后如果这个bean是FactoryBean,会特殊处理,但最终都会进入getBean(),这里没有直接创建bean,而是先从缓存里面拿,如果没有就创建bean,进入getBean

1.1 getBean

进入doGetBean();spring里面带do的方法就是真正做事的。
在这里插入图片描述
getSingleton(beanName);第一次得到的肯定是空,往下跳过不重要的部分
在这里插入图片描述
进入getSingleton
在这里插入图片描述
这行调用了函数式接口的getObject()
在这里插入图片描述
继续进入,就回到了lambda表达式里面的createBean(),开始创建bean的实例

1.2 createBean

进入createBean之后一路往下到达doCreateBean,真正做事的方法
在这里插入图片描述
先进入createBeanInstance,往下走到instantiateBean
在这里插入图片描述
注释是说没有特殊处理:简单的使用无参构造方法
在这里插入图片描述
进入beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
在这里插入图片描述
拿到无参构造器方法保存到BeanDefinition的resolvedConstructorOrFactoryMethod属性
在这里插入图片描述
最终调用newInstance得到了实例对象,其实就是用了反射机制生成对象

二、初始化

在这里插入图片描述
看注释,这里就是初始化开始的地方

2.1 populateBean

populateBean()方法就是属性注入,如果有依赖其他bean就会先完成其他bean的生命周期。这就可能会引发循环依赖,循环依赖的问题我在其他文章中有讲,这里就不详细说了,现在只关心主流程。

2.2 Aware回调

exposedObject = initializeBean(beanName, exposedObject, mbd);–>invokeAwareMethods(beanName, bean);
在这里插入图片描述
Aware的顺序是BeanNameAware–>BeanClassLoaderAware–>BeanFactoryAware

2.3 前置增强postProcessBeforeInitialization

返回到initializeBean方法从wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);进入
在这里插入图片描述
这里执行了所有注册过的BeanPostProcessor的postProcessBeforeInitialization方法,用来处理指定的bean。

2.3.1 @PostConstruct

这里特别注意一下有个CommonAnnotationBeanPostProcessor的增强器,它的构造方法
在这里插入图片描述
会设置初始化注解PostConstruct,它的postProcessBeforeInitialization继承至InitDestroyAnnotationBeanPostProcessor
在这里插入图片描述
postProcessBeforeInitialization执行进入

findLifecycleMetadata(bean.getClass());–>buildLifecycleMetadata()
在这里插入图片描述

这里将@PostConstruct注解的方法加入到了currInitMethods是一个List,最终加入了LifecycleMetadata的initMethods
所以注解@PostConstruct多个方法都会被执行,继续看在哪里执行,回到postProcessBeforeInitialization,从metadata.invokeInitMethods(bean, beanName);进入
在这里插入图片描述
这里执行所有的初始化方法

2.4 执行初始化方法

2.4.1 afterPropertiesSet

返回到initializeBean方法从invokeInitMethods(beanName, wrappedBean, mbd);进入
在这里插入图片描述
先检查是否实现InitializingBean,如果有就执行afterPropertiesSet方法,继续往下
在这里插入图片描述
getInitMethodName()拿到的是手动指定的初始化方法,即xml文件配置bean时指定的init-method属性。之后执行init-method指定的方法

2.4.2 init-method

mbd.getInitMethodName()获取的是initMethodName,看看它在何时赋值
在这里插入图片描述
最终发现是在xml解析的时候赋值的
在这里插入图片描述
在这里插入图片描述
initMethodName类型是String,也就是说只能有一个init-method方法

2.5 后置增强postProcessAfterInitialization

返回到initializeBean方法从wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
进入
在这里插入图片描述
执行所有的后置增强

三、销毁

3.1 destroy

在Spring容器关闭的时候,会去销毁所有的单例Bean
在这里插入图片描述
进入

close()–doClose();–>destroyBeans();–>super.destroySingletons();–> destroySingleton(disposableBeanNames[i]);–>super.destroySingleton(beanName);–>destroyBean(beanName, disposableBean);–>bean.destroy();
在这里插入图片描述

3.1.1 @PreDestroy

bean在销毁的时候会执行DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法
在这里插入图片描述
InitDestroyAnnotationBeanPostProcessor实现了DestructionAwareBeanPostProcessor,因此会执行它的postProcessBeforeDestruction,进而执行metadata.invokeDestroyMethods(bean, beanName);
前面讲过@PostConstruct,在那里同时处理的还有@PreDestroy注解。最终将@PreDestroy注解的方法名添加到了LifecycleMetadata.destroyMethods,而这些方法都将在这里一并执行

3.1.2 DisposableBean

在这里插入图片描述

如上图,如果bean实现了DisposableBean接口,会先执行它自己实现的destroy方法

3.1.3 destroy-method

最后会执行xml指定的destroy-method方法,与init-mehod类似。
在这里插入图片描述
这里的destroyMethodName就是来自xml指定的destroy-method

四、总结

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值