深入源码理解SpringBean生命周期

概述

本文描述下Spring的实例化、初始化、销毁,整个SpringBean生命周期,聊一聊BeanPostProcessor的回调时机、Aware方法的回调时机、初始化方法的回调及其顺序、销毁方法的回调及其顺序、重要的BeanPostProcessor的介绍。
开头是一张我画的调用流转图,然后就是我写的一个Demo通过日志打印了SpringBean的生命周期,最后通过源码慢慢跟进其生命周期。

生命周期流转图

深入源码理解SpringBean生命周期

生命周期Demo

如下对某一个Bean进行getBean操作,最后销毁上下文,通过日志来查看SpringBean的生命周期

代码

package com.deepz.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Slf4j
@Configuration
public class BeanLifeCycleManager {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanLifeCycleManager.class);
        context.getBean("beanLifeCycle");
        context.close();
    }

    @Bean(initMethod = "init", destroyMethod = "destroyMethod")
    public BeanLifeCycle beanLifeCycle() {
        return new BeanLifeCycle();
    }

    interface MyAware extends ApplicationContextAware, EnvironmentAware, BeanFactoryAware {

    }

    @Component
    static class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

        @Override
        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>元信息收集 ,MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) \nbeanDefinition = [{}]\n,beanType = [{}],beanName = [{}]\n", beanDefinition, beanType, beanName);
            }
        }
    }

    @Component
    static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        @Override
        public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>实例化前,InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(Class beanClass,String beanName) \nbeanClass = [{}],beanName = [{}]\n", beanClass, beanName);
            }
            return null;
        }

        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>实例化后,InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(Object bean, String beanName)\nbean = [{}],beanName = [{}]\n", bean, beanName);
            }
            return false;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>初始化前,InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization(Object bean, String beanName)\nbean= [{}],beanName = [{}]\n", bean, beanName);
            }
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>初始化后,InstantiationAwareBeanPostProcessor#postProcessAfterInitialization(Object bean, String beanName)\nbean= [{}],beanName = [{}]\n", bean, beanName);
            }
            return bean;
        }
    }

    public static class BeanLifeCycle implements InitializingBean, MyAware, DisposableBean {
        public void init() {
            log.info(">>>>>>>>>>init-method\n");
        }

        @PostConstruct
        public void postConstruct() {
            log.info(">>>>>>>>>>postConstruct\n");
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            log.info(">>>>>>>>>>afterPropertiesSet\n");
        }

        public void destroyMethod() {
            log.info(">>>>>>>>>>destroy-method\n");
        }

        @Override
        public void destroy() {
            log.info(">>>>>>>>>>DisposableBean-destroy\n");
        }

        @PreDestroy
        public void preDestroy(){
            log.info(">>>>>>>>>>preDestroy\n");
        }

        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            log.info(">>>>>>>>>>BeanFactoryAware#setBeanFactory\n");
        }

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            log.info(">>>>>>>>>>ApplicationContextAware#setApplicationContext\n");
        }

        @Override
        public void setEnvironment(Environment environment) {
            log.info(">>>>>>>>>>EnvironmentAware#setEnvironment\n");
        }
    }
}

执行结果

深入源码理解SpringBean生命周期

实例化前

从createBean开始,见证Bean的实例化过程,首先是Bean实例化前的一个扩展点,它允许你自定义返回Bean实例。(AOP生成代理对象的入口之一,但基本不会走这里)

回调Bean实例化前的方法

AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

深入源码理解SpringBean生命周期

主要是为了回调所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(Class beanClass, String beanName)方法,该方法会返回Object对象,如果返回的Object不为空,则会回调所有BeanPostProcessor的postProcessAfterInitialization(Object bean, String beanName)方法,那么返回的Object则会作为Bean去处理,如果返回Null,那么后续就会交由Spring来实例化、初始化(doCreateBean)。

深入源码理解SpringBean生命周期
深入源码理解SpringBean生命周期
深入源码理解SpringBean生命周期

自定义拦截实例化Bean后回调Bean后置方法

深入源码理解SpringBean生命周期
深入源码理解SpringBean生命周期

实例化

AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
如源码所示,如果上述扩展点没有return,那么就会进入到doCreateBean方法

深入源码理解SpringBean生命周期

首先是对Bean进行实例化,其中包括了构造器推断等,本文不过多聊这块内容,最后会返回BeanWrapper包裹的Bean实例。

深入源码理解SpringBean生命周期

元信息收集

实例化之后Spring通过回调MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName)对一些元信息做了收集维护处理,如@Autowire、@Resource、@PostConstruct 和 @PreDestroy等,为后续属性注入做准备。

深入源码理解SpringBean生命周期

MergedBeanDefinitionPostProcessor的实现类

深入源码理解SpringBean生命周期

MergedBeanDefinitionPostProcessor回调

深入源码理解SpringBean生命周期

初始化

实例化完了,对一些需要收集的信息也准备好了,后续就是进行属性注入和回调初始化方法了,其中populateBean方法是属性填充,initializeBean是回调初始化方法。

深入源码理解SpringBean生命周期

InstatiationAwareBeanPostProcessor回调postProcessAfterInstantiation方法

AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)

深入源码理解SpringBean生命周期

Aware接口回调

AbstractAutowireCapableBeanFactory#initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)

部分Aware接口回调、BeanPostProcessor的初始化前置回调(包括PostConstruct的调用、其余Aware的回调)、afterPropertiesSet回调、自定义init方法回调、BeanPostProcessor的初始化后置回调

深入源码理解SpringBean生命周期

部分Aware回调

AbstractAutowireCapableBeanFactory#invokeAwareMethods(final String beanName, final Object bean

深入源码理解SpringBean生命周期

BeanPostProcessor的初始化前置回调

深入源码理解SpringBean生命周期

重要BeanPostProcessor如下:

ApplicationContextAwareProcessor#postProcessBeforeInitialization(final Object bean, String beanName)回调剩余Aware方法

深入源码理解SpringBean生命周期

InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization(final Object bean, String beanName)回调PostConstruct方法

深入源码理解SpringBean生命周期
深入源码理解SpringBean生命周期

回调初始化方法

AbstractAutowireCapableBeanFactory#invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
先回调InitializingBean的afterPropertiesSet方法,随后回调自定义的init-method

深入源码理解SpringBean生命周期

BeanPostProcessor的初始化后置回调

注意:AOP生成代理的主要入口便是这里的了,对应的BeanPostProcessor->AbstractAutoProxyCreator。(后续单聊AOP相关源码,FLAG)

深入源码理解SpringBean生命周期

销毁

销毁方法最终会走到DisposableBeanAdapter的destroy方法去做处理,与初始化方法类似,这里简单介绍把。
看图就能发现,顺序执行的,先是注解方法,然后是DisposableBean的回调,最后是自定义的销毁方法,就是如此简单。

深入源码理解SpringBean生命周期

(小声)弄了挺久的,如果对你有帮助,或者让你回忆巩固相关知识点了,给我点个”支持”鼓励下..(滑稽),有什么问题欢迎评论讨论。。。

Original: https://www.cnblogs.com/deepSleeping/p/14709552.html
Author: DeepSleeping丶
Title: 深入源码理解SpringBean生命周期

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/715063/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 关于内存数据与 JSON

    正在用 WebBroker 写一个小网站,感受颇多: 1、如果是写一个小东西,应该先考虑下 WebBroker,因为它是分分钟即可上手的。 2、如果要写一个大东西,或许也应该考虑下…

    技术杂谈 2023年5月31日
    096
  • TCP/IP和UDP

    TCP/IP即传输控制/网络协议,是面向连接的协议,发送数据前要先建立连接(发送方和接收方的成对的两个之间必须建 立连接),TCP提供可靠的服务,也就是说,通过TCP连接传输的数据…

    技术杂谈 2023年7月24日
    062
  • 等宽字体、衬线字体与非衬线字体(转)

    本文转自:https://howiezhao.github.io/2018/09/23/code-font/ 等宽字体与比例字体 等宽字体(Monospaced)是指字符宽度相同的…

    技术杂谈 2023年6月1日
    092
  • 安全通告 | 疑似PurpleFox多手段持续实施攻击活动

    安全通告 | 疑似PurpleFox多手段持续实施攻击活动 https://mp.weixin.qq.com/s/Fca_oOiL8oLiEUXGaErWjQ 搜索 复制 Orig…

    技术杂谈 2023年5月31日
    075
  • windows下安装node.js及环境配置、部署项目【转】

    回到顶部 一、操作步骤 ①下载node.js ②安装配置环境变量 ③部署项目启动访问 回到顶部 二、详细步骤 1、选择对应系统下载:https://nodejs.org/en/do…

    技术杂谈 2023年5月31日
    094
  • JDBC事务–自动提交

    通过MYSQLIO执行IO操作。 commit=true/false,代码执行是一样的,都flush出去了,只是服务器端没有执行。 package com.zhuguang.jac…

    技术杂谈 2023年5月30日
    0105
  • 小程聊微服务-增艺眼中的自己主动化測试

    假设说”生活不仅仅有眼前的苟且,还有诗和远方”的话,那么自己主动化測试可以说是非常多測试人员心中的”诗和远方”。 “诗和…

    技术杂谈 2023年5月31日
    0103
  • WCF后传系列(7):消息如何传递之绑定Part 2

    概述 每个服务终结点都包含一个地址Address、一个绑定Binding 和一个契约Contract。契约指定可用的操作,绑定指定如何与服务进行通信,而地址指定查找服务的位置,在W…

    技术杂谈 2023年5月31日
    074
  • mysql(DQL)

    MYSQL(康老师-DQL ) 1:基本的SELECT语句 1.1:基本的SELECT语句的课后练习 2:运算符 2.1:运算符课后练习 3.1排序 3.2分页 4.多表查询 4….

    技术杂谈 2023年7月25日
    059
  • shopify主题Grid模板修改

    Shopify Grid主题是一个砖石风格的主题,非常适合有故事可讲的当代品牌,灵活明亮,具有现代的气息,兼容OS 2.0,独特的布局和强大的导航更方便打造您的品牌。随ytkah一…

    技术杂谈 2023年5月31日
    079
  • 基础篇——Pycharm的安装与使用初学者此篇够用

    简介 Pycharm是python编程过程中最为推荐的编辑调试软件之一,其使用简单,界面友好,也成了学习Python路上必须学会的软件之一,本篇教程简单介绍一下windows用户从…

    技术杂谈 2023年7月23日
    0110
  • 时间序列–Holt-Winters

    Holt-winters 三次指数平滑 原始预测——简单平均——移动平均———加权移动平均 1)单指数平滑法:s(t+1)= ax(t) + (1-a) s(t-1) , a 许更…

    技术杂谈 2023年5月31日
    0102
  • 从Spring中学到的【1】–读懂继承链

    最近看了一些 Spring 源码,发现源码分析的文章很多,而底层思想分析的文章比较少,这个系列文章准备总结一下Spring中给我的启示,包括设计模式思想、SOLID设计原则等,涉及…

    技术杂谈 2023年7月25日
    0118
  • Java根据Freemarker模板生成Word文件

    准备模板 模板 + 数据 = 模型 1、将准备好的Word模板文件另存为.xml文件(PS:建议使用WPS来创建Word文件,不建议用Office) 2、将.xml文件重命名为.f…

    技术杂谈 2023年7月24日
    094
  • LNMP的配置与优化

    LNMP一键安装包是一个用Linux Shell编写的可以为CentOS/RadHat/Fedora、Debian/Ubuntu/Raspbian/Deepin VPS或独立主机安…

    技术杂谈 2023年5月31日
    075
  • kube-scheduler的调度上下文

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年7月24日
    085
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球