@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);
    }
View Code

 

            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;
    }
View Code

        getBeanPostProcessors为了获得所有的BeanPostProcessor  ,在容器初始化的过程中就注册进去了,解释了第一个问题,加@PostConstract注解的方法为什么会执行,执行顺序怎么解释?

        invokeInitMethods 作用又是什么?

     

       afterPropertiesSet  就是实现InitializingBean 接口的重写的方法,解释了测试代码的执行顺序,谜题解开。



posted @ 2019-07-19 10:34  Don'tYouSee  阅读(558)  评论(0)    收藏  举报