学习Spring框架时,了解Bean的生命周期是非常重要的。Bean的生命周期是指,在Spring容器中,Bean从创建到销毁的整个过程。本文将从Spring源码的角度来分析Bean的生命周期。
Spring Bean的生命周期
Bean的生命周期分为以下几个阶段:
- 实例化:Spring容器通过构造器或工厂方法创建出Bean的实例。这个过程是实例化阶段。
- 属性注入:Spring容器利用Setter方法或直接访问成员变量,将Bean的属性设置为相应的值。这个过程是属性注入阶段。
- 初始化:Bean对象的属性都被设置之后,Spring容器会对Bean进行初始化。如果Bean实现了InitializingBean接口,Spring容器会调用它的afterPropertiesSet方法;如果这个Bean配置了init-method,则调用该方法。
- 使用:Bean被初始化之后,可以被容器使用。在使用期间,Bean可能会被多次访问。
- 销毁:当容器关闭时,Spring容器要负责将Bean销毁掉。如果Bean实现了DisposableBean接口,Spring容器会调用它的destroy方法;如果这个Bean配置了destroy-method,则调用该方法。
Spring源码分析
实例化
Bean的实例化是由BeanFactory负责的。BeanFactory在创建Bean的实例时,实际上是通过调用Bean的构造器或通过工厂方法来创建出Bean的实例。这个过程是比较简单的。
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory, BeanDefinitionRegistry {
//创建bean的实例
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
//实例化处理器
InstantiationStrategy InstantiationStrategy strategy = this.getInstantiationStrategy(); //执行实例化过程
Object bean = strategy.instantiate(mbd, beanName, this);
return bean;
}
}
其中,InstantiationStrategy
是一个接口类型,用于定义Bean的实例化策略。Spring提供了两种实例化策略:SimpleInstantiationStrategy
和CglibSubclassingInstantiationStrategy
。
属性注入
Bean的属性注入会在Bean的实例化之后进行。Spring容器会根据Bean的配置信息,调用Setter方法或直接访问成员变量,将Bean的属性设置为相应的值。
public Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//属性填充器
MergedBeanDefinitionPostProcessor pvs = null;
int beanPhase = 0;
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
//判断是否实现了AutowiredAnnotationBeanPostProcessor,实现了则获取到它
if (mbd == null || !mbd.isSynthetic()) {
pvs = this.postProcessMergedBeanDefinition(mbd, bean.getClass(), beanName);
}
if (pvs != null) {
if (pvs.postProcessAfterInstantiation(bean, beanName)) {
return this.wrapBeanIfNecessary(bean, beanName, pvs);
}
}
//应用属性填充器
applyBeanPostProcessorsBeforeApplyingPropertyValues(beanName, bean, mbd);
BeanWrapper bw = null;
//进行属性注入,暴露一个属性值的解析器接口
if (mbd != null) {
bw = this.applyBeanPropertyValues(beanName, bean, mbd, pvs);
}
beanPhase = 2;
//执行验证,类型转换等工作
if (bw != null) {
this.applyBeanPostProcessorsAfterApplyingPropertyValues(bean, beanName);
}
return bean;
}
初始化
Bean的初始化会在Bean的属性注入之后进行,Spring容器会根据Bean的配置信息,调用相应的初始化方法。
public Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//...
//调用InitializingBean.afterPropertiesSet进行初始化
if (mbd == null || !mbd.isSynthetic()) {
//回调调用aware接口的方法
invokeAwareMethods(beanName, bean);
}
//执行BeanPostProcessor的postProcessBeforeInitialization方法
Object wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
try {
//执行初始化(如果实现了InitializingBean接口)和init-method属性指定的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
//...
}
//执行BeanPostProcessor的postProcessAfterInitialization方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); //...
return wrappedBean;
}
其中,InitializingBean
是一个接口类型,包含了一个方法afterPropertiesSet
,该方法会在Bean属性注入之后执行。如果Bean实现了InitializingBean
接口,Spring容器会调用它的afterPropertiesSet
方法。
使用
当Bean经过初始化之后,可以被Spring容器使用。在使用期间,Bean可能会被多次访问。使用期间,Spring容器不会对Bean进行任何修改。
销毁
当Spring容器关闭时,会自动调用销毁方法。如果Bean实现了DisposableBean
接口,Spring容器会调用它的destroy
方法;如果这个Bean配置了destroy-method
,则调用该方法。 、
public void destroyBean(final String beanName, final Object beanInstance) {
//执行销毁操作,先执行destroy方法,然后将其从容器中移除
try {
if (beanInstance instanceof DisposableBean) {
((DisposableBean) beanInstance).destroy();
}
if (this.hasDestructionAwareBeanPostProcessors()) {
for (DestructionAwareBeanPostProcessor processor :getBeanPostProcessorCache().destructionAware) {
processor.postProcessBeforeDestruction(beanInstance, beanName);
}
}
} catch (Throwable ex) {
//...
}
}
总结
Spring Bean的生命周期很清晰的被划分为实例化、属性注入、初始化、使用和销毁这几个阶段。从Spring源码角度来说,很多操作都是通过实现相应的接口,然后通过一些钩子方法来触发的。了解Bean的生命周期是开发Spring应用的必备知识之一。