Spring 提供了多种方法实现 Bean 在初始化和销毁时的回调:
- JSR-250 标准提供了一对注解
@PostConstruct
和@PreDestroy
,用于在类中标识某方法为生命周期钩子。 - 实现了
InitializingBean
接口,可以在afterPropertiesSet()
方法里做初始化之后的任务。实现了DisposableBean
接口,可以在destroy()
方法里做销毁前的任务。 - 在配置 XML 或者
@Bean
注解中,通过init-method
和destroy-method
属性也可以声明生命周期钩子。
初始化之后指对象创建、注入工作结束、其他配置结束后。
执行顺序为:
// 初始化之后
Constructor > @PostConstruct > InitializingBean > init-method
// 销毁前
@PreDestroy > DisposableBean > destroy-method
若想在优雅关闭容器时依次销毁单例,需使用 ConfigurableApplicationContext
类提供的 registerShutdownHook()
方法。
探究生命周期钩子的执行顺序
执行顺序可以在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
类里找到。
以初始化为例,看 initializeBean()
:
invokeAwareMethods()
applyBeanPostProcessorsBeforeInitialization()
invokeInitMethods()
applyBeanPostProcessorsAfterInitialization()
然后看到 invokeInitMethods()
方法里有识别 InitializingBean
接口并调用 afterPropertiesSet()
的逻辑,之后有 invokeCustomInitMethod()
的方法完成 init-method
的逻辑。
而 JSR-250 标准是在 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
类中定义:
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
CommonAnnotationBeanPostProcessor
继承自 InitDestroyAnnotationBeanPostProcessor
类,这个类有以下很有意思的方法:
postProcessBeforeInitialization()
来自BeanPostProcessor
接口postProcessAfterInitialization()
来自BeanPostProcessor
接口postProcessBeforeDestruction()
来自DestructionAwareBeanPostProcessor
接口
能看到 postProcessBeforeInitialization()
和 postProcessBeforeDestruction()
会先调用 findLifecycleMetadata()
,它会调用 buildLifecycleMetadata()
构造生命周期元信息。
buildLifecycleMetadata()
方法里会寻找满足 initAnnotationType
和 destroyAnnotationType
的注解,并加入列表。
回过头看 initializeBean()
先调用了 applyBeanPostProcessorsBeforeInitialization()
,所以 JSR-250 的 @PostConsturct
优先执行。