前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Spring注解驱动开发】@PostConstruct与@PreDestroy源码的执行过程

【Spring注解驱动开发】@PostConstruct与@PreDestroy源码的执行过程

作者头像
冰河
发布2020-10-29 17:09:17
5890
发布2020-10-29 17:09:17
举报
文章被收录于专栏:冰河技术

作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:

https://github.com/sunshinelyz/mykit-delay

PS: 欢迎各位Star源码,也可以pr你牛逼哄哄的代码。

写在前面

在前面的《【String注解驱动开发】你真的了解@PostConstruct注解和@PreDestroy注解吗?》一文中,我们简单的介绍了@PostConstruct注解与@PreDestroy注解的用法,有不少小伙伴纷纷留言说:在Spring中,@PostConstruct注解与@PreDestroy注解标注的方法是在哪里调用的呀?相信大家应该都挺好奇的吧,那今天我们就来一起分析下@PostConstruct注解与@PreDestroy注解的执行过程吧! 项目工程源码已经提交到GitHub:https://github.com/sunshinelyz/spring-annotation

注解说明

@PostConstruct,@PreDestroy是Java规范JSR-250引入的注解,定义了对象的创建和销毁工作,同一期规范中还有注解@Resource,Spring也支持了这些注解。

在Spring中,@PostConstruct,@PreDestroy注解的解析是通过BeanPostProcessor实现的,具体的解析类是org.springframework.context.annotation.CommonAnnotationBeanPostProcessor,其父类是org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor,Spring官方说明了该类对JSR-250中@PostConstruct,@PreDestroy,@Resource注解的支持。

Spring's org.springframework.context.annotation.CommonAnnotationBeanPostProcessor supports the JSR-250 javax.annotation.PostConstruct and javax.annotation.PreDestroy annotations out of the box, as init annotation and destroy annotation, respectively. Furthermore, it also supports the javax.annotation.Resource annotation for annotation-driven injection of named beans.

调用过程

具体过程是,IOC容器先解析各个组件的定义信息,解析到@PostConstruct,@PreDestroy的时候,定义为生命周期相关的方法,组装组件的定义信息等待初始化;在创建组件时,创建组件并且属性赋值完成之后,在执行各类初始化方法之前,从容器中找出所有BeanPostProcessor的实现类,其中包括InitDestroyAnnotationBeanPostProcessor,执行所有BeanPostProcessor的postProcessBeforeInitialization方法,在InitDestroyAnnotationBeanPostProcessor中就是找出被@PostConstruct修饰的方法的定义信息,并执行被@PostConstruct标记的方法。

调用分析

@PostConstruct的调用链如下:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(String, Object, RootBeanDefinition)初始化流程中,先执行org.springframework.beans.factory.config.BeanPostProcessor.postProcessBeforeInitialization(Object, String)方法,然后再执行初始化方法:

代码语言:javascript
复制
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 在执行初始化方法之前:先执行org.springframework.beans.factory.config.BeanPostProcessor.postProcessBeforeInitialization(Object, String)方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //执行InitializingBean的初始化方法和init-method指定的初始化方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

org.springframework.beans.factory.config.BeanPostProcessor.postProcessBeforeInitialization(Object, String)的说明如下:

Apply this BeanPostProcessor to the given new bean instance before any bean initialization callbacks (like InitializingBean's afterPropertiesSet or a custom init-method). The bean will already be populated with property values. The returned bean instance may be a wrapper around the original.

调用时机:在组件创建完属性复制完成之后,调用组件初始化方法之前;

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(Object, String)的具体流程如下。

代码语言:javascript
复制
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        //遍历所有BeanPostProcessor的实现类,执行BeanPostProcessor的postProcessBeforeInitialization
        //在InitDestroyAnnotationBeanPostProcessor中的实现是找出@PostConstruct标记的方法的定义信息,并执行
        result = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

@PreDestroy调用链如下:

@PreDestroy是通过org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(Object, String)被调用(InitDestroyAnnotationBeanPostProcessor实现了该接口),该方法的说明如下:

Apply this BeanPostProcessor to the given bean instance before its destruction. Can invoke custom destruction callbacks. Like DisposableBean's destroy and a custom destroy method, this callback just applies to singleton beans in the factory (including inner beans).

调用时机:该方法在组件的销毁之前调用;

org.springframework.beans.factory.support.DisposableBeanAdapter.destroy()的执行流程如下:

代码语言:javascript
复制
@Override
public void destroy() {
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
        //调用所有DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法
        for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
        }
    }

    if (this.invokeDisposableBean) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
        }
        try {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                    @Override
                    public Object run() throws Exception {
                        ((DisposableBean) bean).destroy();
                        return null;
                }
                }, acc);
            }
            else {
                //调用DisposableBean的销毁方法
                ((DisposableBean) bean).destroy();
            }
        }
        catch (Throwable ex) {
                String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
            if (logger.isDebugEnabled()) {
                logger.warn(msg, ex);
            }
            else {
                logger.warn(msg + ": " + ex);
            }
        }
    }

    //调用自定义的销毁方法
    if (this.destroyMethod != null) {
        invokeCustomDestroyMethod(this.destroyMethod);
    }
    else if (this.destroyMethodName != null) {
        Method methodToCall = determineDestroyMethod();
        if (methodToCall != null) {
            invokeCustomDestroyMethod(methodToCall);
        }
    }
}

所以是先调用DestructionAwareBeanPostProcessor的postProcessBeforeDestruction(@PreDestroy标记的方法被调用),再是DisposableBean的destory方法,最后是自定义销毁方法。

好了,咱们今天就聊到这儿吧!别忘了给个在看和转发,让更多的人看到,一起学习一起进步!!

项目工程源码已经提交到GitHub:https://github.com/sunshinelyz/spring-annotation

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 冰河技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 注解说明
  • 调用过程
  • 调用分析
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档