@PostConstruct
的应用以及与afterPropertiesSet
、init-method
对比请查看《Spring 注解面面通 之 @PostConstruct 应用解析以及与afterPropertiesSet、init-method对比》。
@PostConstruct
与InitializingBean
的源码流程有一部分是重叠的,可以参考《Spring 知识面面通 之 InitializingBean 深入源码解析》。
Spring利用BeanPostProcessor
后置处理器来处理@PostConstruct
和@PreDestroy
注解,InitDestroyAnnotationBeanPostProcessor
是处理@PostConstruct
和@PreDestroy
注解的主要参与者。
源码解析
1) AbstractAutowireCapableBeanFactory
的initializeBean(...)
方法。
① 若Bean
实现了Aware
接口,则触发方法调用。包括:BeanNameAware
、BeanClassLoaderAware
和BeanFactoryAware
。
② 调用注册的BeanPostProcessor
的postProcessBeforeInitialization(...)
方法。其中InitDestroyAnnotationBeanPostProcessor
用来处理@PostConstruct
和@PreDestroy
注解。
③ 调用初始化方法,包括InitializingBean
的afterPropertiesSet()
方法和Bean
的init-method
指定的方法。
④ 调用注册的BeanPostProcessor
的postProcessAfterInitialization(...)
方法。
/**
* 初始化给定的Bean实例,应用工厂回调、init方法和Bean后处理程序.
* 对于传统定义的Bean,从createBean调用,对于现有的Bean实例从initializeBean调用.
* @param beanName 工厂中的Bean名称(用于调试).
* @param bean 需要初始化新的Bean实例.
* @param mbd 创建Bean时使用的Bean定义(如果给定现有的Bean实例,也可以是null).
* @return 初始化的Bean实例(可能被包装).
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 若Bean实现了Aware接口,则触发方法调用.
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// 在Bean初始化前处理BeanPostProcessor.
// !mbd.isSynthetic()表示用户自定义而非框架所有.
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 进行Bean初始化,包括如下两种方式:
// 1.调用InitializingBean.afterPropertiesSet()方法.
// 2.调用Bean配置的init-method方法.
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 在Bean初始化后处理BeanPostProcessor.
// !mbd.isSynthetic()表示用户自定义而非框架所有.
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
2) InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(...)
方法。
① 获取指定Bean
类型生命周期元数据。
② 调用Bean
类型生命周期元数据的初始化方法。
/**
* 初始化之前处理程序.
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 获取Bean类型生命周期元数据.
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 调用元数据的初始化方法.
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
3) InitDestroyAnnotationBeanPostProcessor.invokeInitMethods(...)
方法。
① 遍历搜集到Bean
的所有初始化方法。
② 进行Bean
实际初始化方法调用。
/**
* 调用元数据的初始化方法.
*/
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (LifecycleElement element : initMethodsToIterate) {
if (debug) {
logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
// 调用实际方法.
element.invoke(target);
}
}
}
4) InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata(...)
方法。
① lifecycleMetadataCache
生命周期元数据缓存为空,则重新创建生命周期元数据。
② 采用双重检查锁机制来进行快速检查,尽量减少对锁的使用。
③ 若需新建生命周期元数据,调用buildLifecycleMetadata(...)
创建生命周期元数据。
/**
* 查找指定类型的生命周期元数据.
*/
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
// lifecycleMetadataCache为空,则重新创建生命周期元数据.
if (this.lifecycleMetadataCache == null) {
return buildLifecycleMetadata(clazz);
}
// 首先进行快速检查,只需最少的锁竞争.
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
5) InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata(...)
方法。
① 创建初始化和销毁方法存储集合。
② 查找initAnnotationType
类型注释的方法,放入初始化方法集合。
③ 查找destroyAnnotationType
类型注释的方法,放入初始化方法集合。
/**
* 创建生命周期元数据.
*/
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
final boolean debug = logger.isDebugEnabled();
// 初始化方法集合.
LinkedList<LifecycleElement> initMethods = new LinkedList<>();
// 销毁方法集合.
LinkedList<LifecycleElement> destroyMethods = new LinkedList<>();
Class<?> targetClass = clazz;
do {
// 当前循环初始化方法集合.
final LinkedList<LifecycleElement> currInitMethods = new LinkedList<>();
// 当前循环销毁方法集合.
final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 查找initAnnotationType类型注释的方法.
if (initAnnotationType != null && method.isAnnotationPresent(initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (debug) {
logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
// 查找destroyAnnotationType类型注释的方法.
if (destroyAnnotationType != null && method.isAnnotationPresent(destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (debug) {
logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
// 合并数据.
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
6) CommonAnnotationBeanPostProcessor.CommonAnnotationBeanPostProcessor()
方法。
① 设置@PostConstruct
注解类型,便于后续搜索@PostConstruct
注释的方法。
② 设置@PreDestroy
注解类型,便于后续搜索@PreDestroy
注释的方法。
/**
* 创建CommonAnnotationBeanPostProcessor,
* 初始化和销毁注解类型设置为javax.annotation.PostConstruct和javax.annotation.PreDestroy.
*/
public CommonAnnotationBeanPostProcessor() {
// 设置序号.
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
// 设置@PostConstruct注解类型.
setInitAnnotationType(PostConstruct.class);
// 设置@PreDestroy注解类型.
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
InitDestroyAnnotationBeanPostProcessor.setInitAnnotationType(...)
和InitDestroyAnnotationBeanPostProcessor.setDestroyAnnotationType(...)
方法。
① setInitAnnotationType(...)
指定要检查的初始化注解,指示Bean配置后要调用的初始化方法。由于没有必需的注解属性,可以使用任何自定义注解。一般情况下,使用JSR-250
规范提供的javax.annotation.PostConstruct
。
② setDestroyAnnotationType
指定要检查的销毁注解,指示上下文关闭时要调用的销毁方法。由于没有必需的注解属性,可以使用任何自定义注解。一般情况下,使用JSR-250
规范提供的javax.annotation.PreDestroy
。
/**
* 指定要检查的初始化注解,指示Bean配置后要调用的初始化方法.
* 可以使用任何自定义注解,因为没有必需的注解属性.
* 一般情况下,使用JSR-250规范提供的javax.annotation.PostConstruct.
*/
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
this.initAnnotationType = initAnnotationType;
}
/**
* 指定要检查的销毁注解,指示上下文关闭时要调用的销毁方法.
* 可以使用任何自定义注解,因为没有必需的注解属性.
* 一般情况下,使用JSR-250规范提供的javax.annotation.PreDestroy.
*/
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
this.destroyAnnotationType = destroyAnnotationType;
}
总结
查看源码可以深入了解其实现逻辑,避免应用过程中出现差异。
源码解析基于spring-framework-5.0.5.RELEASE
版本源码。
若文中存在错误和不足,欢迎指正!