深入源码理解SpringBean生命周期
概述
本文描述下Spring的实例化、初始化、销毁,整个SpringBean生命周期,聊一聊BeanPostProcessor的回调时机、Aware方法的回调时机、初始化方法的回调及其顺序、销毁方法的回调及其顺序、重要的BeanPostProcessor的介绍。
开头是一张我画的调用流转图,然后就是我写的一个Demo通过日志打印了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");
}
}
}
执行结果

实例化前
从createBean开始,见证Bean的实例化过程,首先是Bean实例化前的一个扩展点,它允许你自定义返回Bean实例。(AOP也是在这里生成代理对象的)
回调Bean实例化前的方法
AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

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



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


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

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

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

MergedBeanDefinitionPostProcessor的实现类

MergedBeanDefinitionPostProcessor回调

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

InstatiationAwareBeanPostProcessor回调postProcessAfterInstantiation方法
AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)

Aware接口回调
AbstractAutowireCapableBeanFactory#initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
部分Aware接口回调、BeanPostProcessor的初始化前置回调(包括PostConstruct的调用、其余Aware的回调)、afterPropertiesSet回调、自定义init方法回调、BeanPostProcessor的初始化后置回调

部分Aware回调
AbstractAutowireCapableBeanFactory#invokeAwareMethods(final String beanName, final Object bean

BeanPostProcessor的初始化前置回调

重要BeanPostProcessor如下:
ApplicationContextAwareProcessor#postProcessBeforeInitialization(final Object bean, String beanName)回调剩余Aware方法

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


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

BeanPostProcessor的初始化后置回调

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

(小声)弄了挺久的,如果对你有帮助,或者让你回忆巩固相关知识点了,给我点个"支持“鼓励下..(滑稽),有什么问题欢迎评论讨论。。。
深入源码理解SpringBean生命周期的更多相关文章
- Laravel源码分析--Laravel生命周期详解
一.XDEBUG调试 这里我们需要用到php的 xdebug 拓展,所以需要小伙伴们自己去装一下,因为我这里用的是docker,所以就简单介绍下在docker中使用xdebug的注意点. 1.在php ...
- Spring源码系列 — Bean生命周期
前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...
- Vue2.0源码阅读笔记--生命周期
一.Vue2.0的生命周期 Vue2.0的整个生命周期有八个:分别是 1.beforeCreate,2.created,3.beforeMount,4.mounted,5.beforeUpdate,6 ...
- angular11源码探索[DoCheck 生命周期和onChanges区别]
网站 https://blog.thoughtram.io/ https://juristr.com/ https://www.concretepage.com/angular/ https://ww ...
- Spring源码 21 Bean生命周期
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- 【源码】spring生命周期
一.spring生命周期 1. 实例化Bean 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用crea ...
- Spring源码之Bean生命周期
https://www.jianshu.com/p/1dec08d290c1 https://www.cnblogs.com/zrtqsk/p/3735273.html 总结 将class文件加载成B ...
- tomcat源码阅读之生命周期(LifeCycle)
一.事件机制流程: 1. 当外部事件源发生事件(比如点击了按钮,数据发生改变更新等)时,事件源将事件封装成事件对象Event: 2. 将事件对象交由对应的事件派发器Dispatcher ...
- 深入源码理解Spring整合MyBatis原理
写在前面 聊一聊MyBatis的核心概念.Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的.(结合右侧目录了解吧) MyBatis相关核心概念粗略回顾 SqlSess ...
随机推荐
- 【图像处理】OpenCV+Python图像处理入门教程(四)几何变换
这篇随笔介绍使用OpenCV进行图像处理的第四章 几何变换. 4 几何变换 图像的几何变换是指将一幅图像映射到另一幅图像内.有缩放.翻转.仿射变换.透视.重映射等操作. 4.1 缩放 使用cv2. ...
- Elasticsearch 结构化搜索、keyword、Term查询
前言 Elasticsearch 中的结构化搜索,即面向数值.日期.时间.布尔等类型数据的搜索,这些数据类型格式精确,通常使用基于词项的term精确匹配或者prefix前缀匹配.本文还将新版本的&qu ...
- 归并排序(JAVA语言)
public class merge { public static void main(String[] args) { // TODO Auto-generated method stub int ...
- .NET 6 Preview 3 中 ASP.NET Core 的更新和改进
原文:bit.ly/2Qb56NP 作者:Daniel Roth 译者:精致码农-王亮 .NET 6 预览版 3 现已推出,其中包括许多对新的 ASP.NET Core 改进.以下是本次预览版的新内容 ...
- [Fundamental of Power Electronics]-PART II-9. 控制器设计-9.2 负反馈对网络传递函数的影响
9.2 负反馈对网络传递函数的影响 我们已经知道了如何推导开关变换器的交流小信号传递函数.例如,buck变换器的等效电路模型可以表示为图9.3所示.这个等效电路包含三个独立输入:控制输入变量\(\ha ...
- 一文彻底掌握Apache Hudi的主键和分区配置
1. 介绍 Hudi中的每个记录都由HoodieKey唯一标识,HoodieKey由记录键和记录所属的分区路径组成.基于此设计Hudi可以将更新和删除快速应用于指定记录.Hudi使用分区路径字段对数据 ...
- OOUnit1Summary
一.前三次作业内容分析 前言 第一单元的作业以表达式求导为主题,分三次要求逐步增加,难度逐步提高.这三次作业下来,本人既有收获,也有遗憾,因此通过接下来的内容对我这三次作业进行分析和总结,希望能能为我 ...
- 腾讯高级工程师带你玩转打包利器webpack
随着前端领域飞速发展,webpack将前端不断出现的新模块.新资源.新需求,进行自动化整合.梳理.输出,极大提高了我们的工作效率,成为前端构建领域里最炙手可热的构建工具. 不少人webpack 的使用 ...
- get_started_3dsctf_2016-Pwn
get_started_3dsctf_2016-Pwn 这个题确实有点坑,在本地能打,在远程就不能打了,于是我就换了另一种方法来做. 确这个题是没有动态链接库,且PIE是关的,所以程序的大部分地址已经 ...
- 【笔记】《Redis设计与实现》chapter17 集群
17.1 节点 启动节点 Redis服务器启动时会根据cluster-enabled配置选项是否为yes来决定是否开启服务器的集群模式 节点会继续使用redisServer结构来保存服务器的状态,使用 ...