spring bean 的生命周期
在scope为单例模式下,spring bean的生命周期如下图
从代码中对照
class AbstractAutowireCapableBeanFactory
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
上述流程位置追踪:
具体来说:
1.首先实例化bean对象。
如果是beanFactory容器,当客户请求一个尚未实例化的bean时,或需要依赖注入一个尚未实例化的bean时,容器会通过调用createBean进行该bean的实例化。
对于ApplicationContext容器,在容器启动结束后,就会实例化所有bean。
容器通过调用beanDefinition获取bean信息进行实例化,此步骤仅仅是简单的实例化,并未进行依赖注入。
2.设置对象属性,进行依赖注入。
依赖注入过程及如何避免循环依赖的,可见我之前的文章。
3.检查Aware相关接口,设置相关依赖。
这一步主要检查以下几个接口,
BeanNameAware接口,如果实现了该接口,会调用setBeanName(String beanId)方法,将beanId传进来。
BeanFactoryAware接口,如果实现了该接口,会调用setBeanFactory()方法,将容器本身传进来。(可以用该容器获取到其他bean)
ApplicationContextAware接口,如果实现了该接口,会调用SetApplicationContext(ApplicationContext)方法,传入spring上下文,即ApplicationContext这个容器。ApplicationContext是BeanFactory的子类,有更多方法,更易于使用。
经过以上几步,bean已经被正确的构造了,如果你想在使用前再增加一些自定义方法,可以使用以下步骤。
4.BeanPostProcesssor接口
如果bean实现了BeanPostProcesssor接口,则调用前置处理方法。
即PostProcessBeforeInitialzation(Object bean,String beanName),当前初始化的bean被传进来,我们就可以进行自定义设置了。由于此步设置发生在InitialzationBean方法之前执行,所以成为前置处理。
对应的PostProcessAfterIntialzation(Object bean,String beanName)即是后置处理
5.如果实现了InitialzationBean接口。
该接口只有一个方法,即afterPropertiesSet(),执行该方法。
该步骤跟BeanPostProcessor接口不通,本步骤没有传入bean,所以我们无法处理bean本身,只能添加一些相关的业务逻辑。
使用InitialzationBean的方式有两种,一个是直接实现该接口,在实现方法中写业务逻辑。
还有一种便捷方法,可以减少代码入侵。即使用init-method注解,使用该属性指向我们的自定义方法。这样在bean初始化时便会执行对应的方法。
先执行afterPropertiesSet()方法,再执行init-method()方法
6.如果实现了BeanPostProcessor接口,调用后置方法。
即调用PostAfterInitialzation(Obeject bean,String beanName)方法
此时bean已经准备就绪了,可以被应用程序使用了,它将一直驻留在上下文中,知道容器被销毁。
7.如果bean实现了DisposableBean接口
则在销毁该bean之前,调用对应的实现方法destory()。
跟InitialzationBean接口对应,也有一个对应的destory-method,指定对应的方法。就可以在销毁bean前执行对应的逻辑了。
执行destory()方法,再执行destory-method方法。
以上就是spring bean的生命周期了。
talk is cheap,show me the code!
下面是每一步具体的应用举例
*实现 Aware 接口
@Component
public class SpringLifeCycleAware implements ApplicationContextAware {
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleAware.class);
private ApplicationContext applicationContext ;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext ;
LOGGER.info("SpringLifeCycleAware start");
}
}
BeanPostProcessor 增强处理器
@Component
public class SpringLifeCycleProcessor implements BeanPostProcessor {
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleProcessor.class);
/**
* 预初始化 初始化之前调用
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("annotationBean".equals(beanName)){
LOGGER.info("SpringLifeCycleProcessor start beanName={}",beanName);
}
return bean;
}
/**
* 后初始化 bean 初始化完成调用
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("annotationBean".equals(beanName)){
LOGGER.info("SpringLifeCycleProcessor end beanName={}",beanName);
}
return bean;
}
}
InitializingBean, DisposableBean 接口
@Service
public class SpringLifeCycleService implements InitializingBean,DisposableBean{
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycleService.class);
@Override
public void afterPropertiesSet() throws Exception {
LOGGER.info("SpringLifeCycleService start");
}
@Override
public void destroy() throws Exception {
LOGGER.info("SpringLifeCycleService destroy");
}
}
自定义初始化和销毁方法
@Configuration
public class LifeCycleConfig {
@Bean(initMethod = "start", destroyMethod = "destroy")
public SpringLifeCycle create(){
SpringLifeCycle springLifeCycle = new SpringLifeCycle() ;
return springLifeCycle ;
}
}
public class SpringLifeCycle{
private final static Logger LOGGER = LoggerFactory.getLogger(SpringLifeCycle.class);
public void start(){
LOGGER.info("SpringLifeCycle start");
}
public void destroy(){
LOGGER.info("SpringLifeCycle destroy");
}
}
OK,现在用例也有了,那么问题来了
spring bean生命周期有什么可扩展的?
spring bean生命周期中有很多可以扩展的地方。
比如我们可以将生命周期简单归为以下步骤
实例化-》属性填充-》执行Aware接口-》初始化-》应用-》销毁
那么如果我们实现了BeanPostProcessor子类InstantiationAwareBeanPostProcessorAdapter这样一个适配器,既可以在以下几个点进行扩展
EP1-》实例化-》EP2-》属性填充-》EP3-》执行Aware接口-》EP4-》初始化-》应用-》销毁
具体实现如下:
扩展点和对应的方法如下:
1.实例化前的扩展点EP1 => postProcessBeforeInstantiation
2.实例化后的扩展点EP2 => postProcessAfterInstantiation
3.初始化前的扩展点EP3 => postProcessBeforeInitialization
4.初始化后的扩展点EP4 => postProcessAfterInitialization
以上。