深入源码理解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 ...
随机推荐
- linux 系统用户与用户组管理
关于/etc/passwd和/etc/shadow /etc/passwd 第1个字段为用户名(第一行中的root就是用户名)第2个字段存放的是该账号的口令.第3个字段为一个数字,这个数字代表的用户标 ...
- python 序列与字典
序列概念: 序列的成员有序排列,可以通过下标访问到一个或几个元素,就类似与c语言的数组. 序列的通用的操作: 1:索引 11 = [1,2,3,4] 11[0] = 1 2:切片 11[1,2,3,4 ...
- Apache Pulsar 在能源互联网领域的落地实践
关于 Apache Pulsar Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息.存储.轻量化函数式计算为一体,采用计算与存储分离架构设计,支 ...
- GitlabCI/CD&Kubernetes项目交付流水线实践
GitlabCI实践 GitLabCI/CD基础概念 为什么要做CI/CD? GitLab CI/CD简介 GitLabCI VS Jenkins 安装部署GitLab服务 GitLabRunner实 ...
- KMP字符串匹配学习笔记
部分内容引自皎月半洒花的博客 模式串匹配问题模型给定一个需要处理的文本串和一个需要在文本串中搜索的模式串,查询在该文本串中,给出的模式串的出现有无.次数.位置等.算法思想每次失配之后不会从头开始枚举, ...
- [矩阵乘法] PKU3233 Matrix Power Series
[ 矩 阵 乘 法 ] M a t r i x P o w e r S e r i e s [矩阵乘法]Matrix Power Series [矩阵乘法]MatrixPowerSeries Desc ...
- 201871030118-雷云云 实验二 个人项目—D{0-1}背包问题项目报告
项目 内容 课程班级博客链接 班级博客 这个作业要求链接 作业链接 我的课程学习目标 1.了解并掌握psp2.掌握软件项目个人开发流程3.掌握Github发布软件项目的操作方法 这个作业在哪些方面帮助 ...
- SpringBoot(九篇)
(一) SpringBootCLI安装 (二)SpringBoot开发第一个应用 (三)SpringBoot pom.xml配置文件详解 (四)SpringBoot起步依赖Starters详解 (五) ...
- 记一次metasploitable2内网渗透之8180端口tomcat
扫描网段存活主机,确定内网metasploitable主机位置 nmap -T4 -sP 192.168.1.0/24 对目标主机进行扫描端口开放和系统信息 nmap -T4 -sV -Pn 192. ...
- mp4视频中插入文字
最近接到一个需求,需要往mp4中动态插入文字,并且mp4中的乌云能在文字上有飘动的效果,一开始想用canvas,但是由于本人经验不足,没什么思路,看到css3有一个属性:mix-blend-mode, ...