Spring Bean的生命周期
综上为Spring的生命周期,主要生命周期为标颜色的部分,总共分四步。
- 实例化bean(createBeanInstance)
- 属性填充(populateBean)
- 初始化bean(initializeBean)
- 销毁
以下从源码阶段对Spring的生命周期进行分析
上面主要的代码实现都在doCreate()方法中。可以看到,在当前方法中有Spring Bean生命周期的三个步骤如下
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
//1、实例化bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//2、属性填充
populateBean(beanName, mbd, instanceWrapper);
//3、初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
关于每个阶段的扩展点将会在下面的不同阶段进行穿插引入解读
一、实例化Bean
1、实例化Bean
对于BeanFactory容器,当客户向容器请求一个未初始化的Bean,或者初始化Bean的时候需要注入另外一个尚未初始化的依赖时,容器就会调用createBean方法。
对于ApplicationContext容器,当容器启动后,便会实例化所有的bean.
实例化对象被包含在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性。
啥是BeanWrapper?
BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器,由于BeanWrapper接口是PropertyAccessor的子接口,因此其也可以设置以及访问被包装对象的属性值。BeanWrapper大部分情况下是在spring ioc内部进行使用,通过BeanWrapper,spring ioc容器可以用统一的方式来访问bean的属性
实例化bean之后会得到一个BeanWrapper对象
2、实例化的前置操作和后置操作
先了解下InstantiationAwareBeanPostProcessor是个啥?
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;
}
...
BeanPostProcessor的子接口,它添加一个实例化之前的回调,以及实例化之后但在显式属性设置或自动装配发生之前的回调
那么在实例化bean的过程中是如何体现前置调用和后置调用的?
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {
//实例化之前的回调,这个方法内部体现了
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//实例化之后的回调
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
///属性赋值操作。。。
二、属性填充
1、属性填充
属性填充的方法为populateBean()
主要目的是将RootBeanDefinition的值填充给BeanWrapper对象的。
这里面包括了根据类型填充对象和根据name填充对象,具体可以看下文章:https://blog.csdn.net/qq_35712465/article/details/120086429
2、检查Aware相关接口并设置相关依赖
Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean
关于Aware的了解可以去看下文章:https://blog.csdn.net/qq_35712465/article/details/120086429
三、初始化阶段
1、初始化bean
在bean实例化之前来执行用户自定义的方法,这种指定有两种方式可以进行指定
- 在配置文件中配置init-method属性
- 实现InitializingBean 接口,来自定义afterPropertiesSet()方法
想了解更多初始化bean 相关的可以看下文章:https://blog.csdn.net/qq_35712465/article/details/120086429
2、初始化的前置操作和后置操作
这里的前置操作和后置操作在实例化代码中的体现为:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//初始化前的前置操作
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//初始化
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
//初始化后的后置操作
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这里的是实例化操作是基于BeanPostProcessor接口的,注意,与上面有点区别,上面是使用了BeanPostProcessor的子接口
四、销毁
- 调用DiposibleBean的Destory()方法
- destory-method指定函数
- @PreDestroy
这两种方法并不是真正销毁bean的方法,它只是在销毁bean之前执行的你自定义的一个逻辑而已。