概述
本文主要讲解bean生命周期中初始化相关后置处理器
生命周期回调方法
生命周期回调方法的实现对应着spring中InitDestroyAnnotationBeanPostProcessor这个后置处理器
在bean的生命周期中,当bean进入到初始化前这一阶段的时候,就调用其postProcessBeforeInitialization方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// @PostConstruct
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {......}
return bean;
}
LifecycleMetadata ,从这个名字就能知道,里面存储着申明周期回调方法的相关信息,的确,spring就是通过反射的方式,获取到当前bean里面标注了生命周期回调方法注解的方法,然后封装到这个对象里面
接下来看看spring具体如何去找这些注解的
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
...}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
...}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
其核心的方法时ReflectionUtils.doWithLocalMethods,这是spring内部的反射工具类,在doWithLocalMethods,通过反射获取到所有的Method对象,然后回调 作为参数的表达式,就会去判断 method.isAnnotationPresent(this.initAnnotationType)
而initAnnotationType是什么呢??
/*....
....
* is the JSR-250 {@link javax.annotation.PostConstruct} annotation.
*/
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
this.initAnnotationType = initAnnotationType;
}
通过spring 的注解就可以很轻易的发现,initAnnotationType就是@PostConstruct这个注解
再回到buildLifecycleMetadata这个方法里面,如果说找到了标有@PostConstruct这个注解的方法就会将其包装为LifecycleElement
然后放入 currInitMethods
如果说找到了标有@PreDestroy的方法也会将其包装为LifecycleElement ,添加到currDestroyMethods这个集合中
完成上述的操作,实例对象有了,要执行的方法也有了,那么就可以通过反射进行回调执行了
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()) {
for (LifecycleElement element : initMethodsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
element.invoke(target);
}
}
}
总结
@PostConstruct的实现就是InitDestroyAnnotationBeanPostProcessor中postProcessBeforeInitialization这个方法的实现,
而这一步骤正是对应着bean的生命周期中的初始化前,具体实现就是先通过反射将所有的方法进行循环遍历,找到标注了@PostConstruct
和@PreDestroy的方法然后将其放入集合,最后再循环获取到集合里的方法,然后通过反射进行回调