@PostConstruct和@PreDestroy
@PostConstruct修饰的方法将会在依赖注入完成后被自动调用
@PreDestroy修饰的方法会在服务器卸载的时候运行,并且只会被服务器调用一次
话不多说,看一段测试代码(基于SpringBoot项目)
@Configuration
public class LifeCycleBean implements InitializingBean, DisposableBean {
//Bean在实例化的过程中的优先级:
//Constructor(构造器) > @PostConstruct > InitializingBean > init-method(xml配置)
@PostConstruct
public void init() {
System.out.println("--------------------postContruct-----------------");
}
@PreDestroy
public void destory() {
System.out.println("--------------------PreDestroy-----------------");
}
/**
* 重写InitializingBean的afterPropertiesSet
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("--------------------InitializingBean-----------------");
}
/**
* 重写DisposableBean的destroy
*/
@Override
public void destroy() throws Exception {
System.out.println("--------------------DisposableBean-----------------");
}
}
Springboot启动类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
applicationContext.close();//关闭容器
}
}
测试结果
--------------------postContruct------------
--------------------InitializingBean---------
--------------------PreDestroy---------------
--------------------DisposableBean-----------
分析:基于上面的测试结果引发了两个问题 1.为什么method会被自动调用 2.为什么是这种执行顺序
首先要了解一个顶层接口 BeanPostProcessor

Spring的Bean实例化时候的前置处理器(postProcessBeforeInitialization)和后置处理器(postProcessAfterInitialization)
再来看一下CommonAnnotationBeanPostProcessor的类图

CommonAnnotationBeanPostProcessor类的构造方法

比如InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization方法

findLifecycleMetadata的源码
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) { if (this.lifecycleMetadataCache == null) { // Happens after deserialization, during destruction... return buildLifecycleMetadata(clazz); } // Quick check on the concurrent map first, with minimal locking. 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; } 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 -> { if (initAnnotationType != null) { if (method.getAnnotation(initAnnotationType) != null) { LifecycleElement element = new LifecycleElement(method); currInitMethods.add(element); if (debug) { logger.debug("Found init method on class [" + clazz.getName() + "]: " + method); } } } if (destroyAnnotationType != null) { if (method.getAnnotation(destroyAnnotationType) != null) { 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); }
invokeInitMethods方法

element.invoke(target)方法

那么前面的前置处理器和后置处理器是什么时候出发呢? AbstractAutowireCapableBeanFactory中的initializeBean方法中似乎找到了答案。


//初始容器创建的Bean实例对象 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { //JDK的安全机制验证权限 if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { //调用Aware接口的实现方法 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; //对BeanPostProcessor后置处理器的postProcessBeforeInitialization //回调方法的调用,为Bean实例初始化前做一些处理 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } //调用Bean实例对象初始化的方法,这个初始化方法是在Spring 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); } //对BeanPostProcessor后置处理器的postProcessAfterInitialization //回调方法的调用,为Bean实例初始化之后做一些处理 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } //调用BeanPostProcessor后置处理器实例对象初始化之前的处理方法 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { //调用Bean实例所有的后置处理中的初始化前处理方法,为Bean实例对象在 //初始化之前做一些自定义的处理操作 Object current = beanProcessor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
getBeanPostProcessors为了获得所有的BeanPostProcessor ,在容器初始化的过程中就注册进去了,解释了第一个问题,加@PostConstract注解的方法为什么会执行,执行顺序怎么解释?
invokeInitMethods 作用又是什么?

afterPropertiesSet 就是实现InitializingBean 接口的重写的方法,解释了测试代码的执行顺序,谜题解开。
=========================================================================================================================================
我只是一粒简单的石子,未曾想掀起惊涛骇浪,也不愿随波逐流
每个人都很渺小,努力做自己,不虚度光阴,做真实的自己,无论是否到达目标点,既然选择了出发,便勇往直前
我不能保证所有的东西都是对的,但都是能力范围内的深思熟虑和反复斟酌

浙公网安备 33010602011771号