springBean生命周期解析
本文基于Spring5.3.7
参考:
kykangyuky Spring中bean的生命周期
阿斌Java之路 SpringBean的生命周期,
杨开振 JavaEE互联网轻量级框架整合开发
黑马程序员 JavaEE企业级应用开发教程
马士兵 Spring源码讲解
一. SpringBean生命周期流程图

二. 示例代码
1. 定义果汁描述实体类
package com.xiaobai.spring_bean_life_cycle;import lombok.Data;
import lombok.extern.slf4j.Slf4j;/*** @author wangtw* @date 2023/6/24 16:38* @description 果汁描述实体类*/
@Slf4j
@Data
public class Source {public Source() {log.info("source实例化");}/*** 水果*/private String fruit;/*** 糖量*/private String sugar;/*** 大小*/private String size;
}
2. 定义果汁生成器
package com.xiaobai.spring_bean_life_cycle;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;/*** @author wangtw* @date 2023/6/24 16:28* @description 果汁生成器*/
@Slf4j
@Data
public class JuiceMaker implements BeanNameAware, BeanFactoryAware,ApplicationContextAware, InitializingBean, DisposableBean {public JuiceMaker(){log.info("juice实例化");}private String beverageShop;private Source source;/*** 自定义初始化方法*/public void init() {log.info("【{}】执行自定义初始化方法", this.getClass().getSimpleName());}/*** 自定义销毁方法*/public void myDestroy() {log.info("【{}】执行自定义销毁方法", this.getClass().getSimpleName());}public String makeJuice() {String juice = "这是一杯由" + beverageShop + "饮品店,提供的" + source.getSize() + source.getSugar() + source.getFruit();return juice;}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info("【{}】调用BeanFactoryAware接口的setBeanFactory方法", this.getClass().getSimpleName());}@Overridepublic void setBeanName(String s) {log.info("【{}】调用BeanNameAware接口的setBeanName方法", this.getClass().getSimpleName());}@Overridepublic void destroy() throws Exception {log.info("调用接口DisposableBean的destroy方法");}@Overridepublic void afterPropertiesSet() throws Exception {log.info("【{}】调用InitializingBean接口的afterPropertiesSet方法", this.getClass().getSimpleName());}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {log.info("【{}】调用ApplicationContextAware接口的setApplicationContext方法", this.getClass().getSimpleName());}
}
3. 定义Bean实现BeanPostProcessor接口
package com.xiaobai.spring_bean_life_cycle;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;/*** @author wangtw* @date 2023/6/24 16:07* @description*/
@Slf4j
public class BeanPostProcessorImpl implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {log.info("【{}】对象{}预初始化开始", bean.getClass().getSimpleName(), beanName);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {log.info("【{}】对象{}预初始化完成", bean.getClass().getSimpleName(), beanName);return bean;}
}
4. 定义SpringBean配置类
package com.xiaobai.spring_bean_life_cycle;import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author wangtw* @date 2023/6/25 10:33* @description Spring配置类*/
@Configuration
public class LifeConfiguration {@Bean("beanPostProcessor")public BeanPostProcessor beanPostProcessor() {return new BeanPostProcessorImpl();}@Bean("source")public Source source() {Source source = new Source();source.setFruit("橙汁");source.setSugar("少糖");source.setSize("大杯");return source;}@Bean(value = "juiceMaker", initMethod = "init", destroyMethod = "myDestroy")public JuiceMaker juiceMaker() {JuiceMaker juiceMaker = new JuiceMaker();juiceMaker.setSource(source());juiceMaker.setBeverageShop("贡茶");return juiceMaker;}
}
5. 测试类及输出结果
package com.xiaobai.spring_bean_life_cycle;import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @author wangtw* @date 2023/6/25 10:40* @description springBean生命周期测试类*/
@Slf4j
public class SpringBeanLifeTest {@Testpublic void testLifeCycle() {ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(LifeConfiguration.class);JuiceMaker juiceMaker = (JuiceMaker) context.getBean("juiceMaker");log.info(juiceMaker.makeJuice());context.close();}
}

三. 源码解析
(一)Bean实例化
1. 根据注解加载Bean
org.springframework.beans.factory.config.BeanFactoryPostProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)
org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
2. 在SpringBean实例化前会把扫描到的类加载到BeanDefinition中,然后将BeanDefinition中的信息注册到Spring容器中
org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext()
org.springframework.context.annotation.AnnotationConfigApplicationContext#register
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean
org.springframework.beans.factory.support.BeanDefinitionRegistry#registerBeanDefinition
3. 完成了BeanDefinition注册后,对Bean进行实例化
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
(二)初始化
1. 属性赋值
(1)自定义对象属性赋值
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
(2)容器对象赋值:检查aware接口并设置相关依赖(aware接口用于标记,判断调用什么方法)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
2. 执行前置处理方法
org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
3. 执行初始化方法
(1)检测Bean是否实现了InitializingBean接口
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
(2)调用afterPropertiesSet方法
org.springframework.beans.factory.InitializingBean#afterPropertiesSet
(3)调用自定义初始化方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeCustomInitMethod
4. 执行后置处理方法
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
创建代理对象
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
org.springframework.aop.framework.AopProxy#getProxy(java.lang.ClassLoader)
(三)使用
(四)销毁
相关文章:
springBean生命周期解析
本文基于Spring5.3.7 参考: kykangyuky Spring中bean的生命周期 阿斌Java之路 SpringBean的生命周期, 杨开振 JavaEE互联网轻量级框架整合开发 黑马程序员 JavaEE企业级应用开发教程 马士兵 Spring源码讲解 一. SpringBean生命周期流程图 二. 示例代码 …...
人工智能轨道交通行业周刊-第54期(2023.7.31-8.6)
本期关键词:BIM智能运维、铁水联运、编组站美容、鸿蒙4.0、LK-99完全悬浮 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通RailMetro轨道世界…...
Docker Compose 使用方法
目录 前言 安装 Docker Compose Ubuntu 安装与更新 Red Hat 安装与更新 验证是否安装 Docker Compose 创建 docker-compose.yml 文件 创建一个MySQL 与 tomcat 示例 使用Docker Compose启动服务 前言 Docker Compose 是一个工具,旨在帮助定义和 共享多容器…...
HTML 初
前言 HTML的基本骨架 HTML基本骨架是构建网页的最基本的结果。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…...
IPv6地址分类,EUI-64转换规则
1、可聚合的单全球单播地址Global Unique Address: Aggregate global unicast address,前3位是001,即2000::/3,目前IANA已经将一部分可聚合全球单播进行了专门使用,如:2001::/16用于IPV6互联网,…...
Nginx安装部署
什么是Nginx? Nginx(发音同engine x)是一款由俄罗斯程序员Igor Sysoev所开发轻量级的网页服务器、反向代 理服务器以及电子邮件(IMAP/POP3)代理服务器。 Nginx 因具有高并发(特別是静态资源)、 占用系统资…...
物联网|按键实验---学习I/O的输入及中断的编程|读取I/O的输入信号|中断的编程方法|轮询实现按键捕获实验-学习笔记(13)
文章目录 实验目的了解擒键的工作原理及电原理图 STM32F407中如何读取I/O的输入信号STM32F407对中断的编程方法通过轮询实现按键捕获实验如何利用已有内工程创建新工程通过轮询实现按键捕获代码实现及分析1 代码的流程分析2 代码的实现 Tips:下载错误的解决 实验目的 了解擒键…...
Hadoop-HDFS的Namenode及Datanode(参考Hadoop官网)
HDFS有什么特点,被设计做什么 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。有一下几个特点: HDFS是一个高度容错性的系统,具有高容错、高可靠性、高扩展性的特点,适合部…...
C:通过alarm发送信号
可以通过alarm定时发送SIGALRM信号: #include <unistd.h> unsigned int alarm(unsigned int seconds); alarm()函数用来在seconds秒之后安排发送一个SIGALRM信号,如果seconds为0,将取消所有已设置的闹钟请求。alarm()函数的返回值是以前…...
如何将 dubbo filter 拦截器原理运用到日志拦截器中?
业务背景 我们希望可以在使用日志拦截器时,定义属于自己的拦截器方法。 实现的方式有很多种,我们分别来看一下。 拓展阅读 java 注解结合 spring aop 实现自动输出日志 java 注解结合 spring aop 实现日志traceId唯一标识 java 注解结合 spring ao…...
【java】【maven】【基础】MAVEN安装配置介绍
目录 1 下载 2 安装-windows为例 3 配置环境变量 3.1 JAVA_HOME 3.2 MAVEN_HOME 3.3 PATH 3.4 验证 4 MAVEN基础概念 4.1 仓库概念 4.2 坐标概念 4.2.1 打开网址 4.2.2 输入搜索内容junit 4.2.3 找到对应API名称点击 4.2.4 点击对应版本 4.2.5 复制MAVEN坐标 4.3 配置…...
【C语言进阶】指针的高级应用(下)
文章目录 一、指针数组与数组指针1.1 指针数组与数组指针的表达式 二、函数指针2.1 函数指针的书写方式 三、二重指针与一重指针3.1 二重指针的本质3.2 二重指针的用法3.3 二重指针与数组指针 总结 一、指针数组与数组指针 (1)指针数组的实质是一个数组,这个数组中存…...
【uniapp APP隐藏顶部的电量,无线,时间状态栏与导航栏】
uniapp APP隐藏顶部的电量,无线,时间状态栏 如下代码配置(在一个页面设置这个段代码,所有页面都会消失) onShow() {// #ifdef APP-PLUS// 隐藏顶部电池,时间等信息 plus.navigator.setFullscreen(true);//隐藏虚拟按…...
微信小程序前后页面传值
微信小程序前后页面传值 从前一个页面跳转到下一个页面,如何传递参数?从后一个页面返回前一个页面,如何回调参数? 向后传值 从前一个页面跳转到下一个页面并传值。 前页面:在跳转链接中添加参数并传递 wx.navigat…...
没有jodatime,rust里怎么比较两个日期(时间)的大小呢?
关注我,学习Rust不迷路!! 在 Rust 中,比较两个日期的大小有多种方法。以下是列举的四种常见方法: 1. 使用 PartialOrd trait: use chrono::prelude::*;fn main() {let date1 NaiveDate::from_ymd(2022,…...
【雕爷学编程】Arduino动手做(186)---WeMos ESP32开发板18
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…...
C语言假期作业 DAY 14
一、选择题 1、有以下函数,该函数的功能是( ) int fun(char *s) {char *t s;while(*t);return(t-s); } A: 比较两个字符的大小 B: 计算s所指字符串占用内存字节的个数 C: 计算s所指字符串的长度 D: 将s所指字符串复制到字符串t中 答案解析 …...
Maven-生命周期及命令
关于本文 ✍写作原因 之前在学校学习的时候,编写代码使用的项目都是单体架构,导入开源框架依赖时只需要在pom.xml里面添加依赖,点一下reload按钮即可解决大部分需求;但是在公司使用了dubbo微服务架构之后发现只知道使用reload不足…...
常温超导:AI在研发中的潜力
目录 引言:1. 常温超导的挑战:2. AI在材料研究中的作用:3. AI在理论模型中的作用:4. AI与实验室合作的潜力:结论: 引言: 常温超导一直被认为是科学界的“圣杯”,可以在室温条件下实…...
【C++】开源:Eigen3矩阵与线性代数库配置使用
😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍Eigen3矩阵与线性代数库配置使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下&…...
AI编程革命:重塑程序员未来(一)
AI编程时代到来AI不会让程序员消失,但会深刻重塑这个职业。当代码生成变得轻而易举,程序员 的角色将从“代码编写者”升级为“问题解决者”与“架构设计师”。未来的核心竞争力,在于 理解复杂业务、设计系统逻辑,并用人类独有的创…...
英飞凌TC3XX时钟系统实战:从PLL配置到CCU分频的避坑指南
英飞凌TC3XX时钟系统实战:从PLL配置到CCU分频的避坑指南 在嵌入式系统开发中,时钟系统如同人体的神经系统,为整个芯片提供精准的时序控制和同步信号。作为英飞凌AURIX™系列中的旗舰产品,TC3XX微控制器凭借其高度可配置的时钟架构…...
seo推广如何策划
SEO推广如何策划:全面指南 在当今数字化时代,搜索引擎优化(SEO)推广已成为企业提升网站流量、增加品牌曝光的关键手段。如何有效地策划一套适合自己业务的SEO推广方案却不是件容易的事。本文将从SEO推广的基础概念、问题分析、原…...
从理论到实践:手把手教你用MATLAB构建LSSVR代理模型
1. 代理模型与LSSVR基础认知 第一次接触"代理模型"这个概念时,我正被一个汽车悬架优化项目折磨得焦头烂额——每次修改参数都要运行长达6小时的有限元仿真。直到导师扔给我一篇关于LSSVR的论文,才真正体会到什么叫"山重水复疑无路&#x…...
丁二酸酯PEG氨基叔丁氧羰基,NHBoc-PEG-SA,可与胺基、羟基等基团发生缩合反应
一.名称英文名称:SA-PEG-NHBoc,Succinic Acid-PEG-NHBoc,NHBoc-PEG-SA,NHBoc-PEG-Succinic Acid中文名称:丁二酸酯聚乙二醇氨基叔丁氧羰基,丁二酸酯PEG氨基叔丁氧羰基分子量:1k,2k&a…...
油猴插件开发必备:VSCode中高效使用Tampermonkey API的10个技巧
油猴插件开发必备:VSCode中高效使用Tampermonkey API的10个技巧 在浏览器扩展开发领域,Tampermonkey(油猴)以其轻量级和灵活性赢得了大量开发者的青睐。作为一款用户脚本管理器,它允许开发者通过JavaScript快速定制网页…...
28GHz毫米波滤波器设计实战:用SynMatrix快速搞定SIW带通滤波器(附完整参数)
28GHz毫米波滤波器设计实战:SynMatrix工具链的高效应用指南 在毫米波频段,滤波器设计一直是射频工程师面临的重大挑战之一。尤其是当工作频率上升到28GHz甚至更高时,传统设计方法往往陷入反复迭代的泥潭,耗费大量时间在仿真优化与…...
Allegro 17.4表贴焊盘设计实战:用Pad Designer快速创建符合IPC标准的SMD焊盘
Allegro 17.4表贴焊盘设计实战:从零构建符合IPC标准的SMD封装 在高速PCB设计领域,表贴器件(SMD)的焊盘设计质量直接影响焊接良率和信号完整性。Cadence Allegro 17.4的Pad Designer工具提供了专业级的焊盘设计解决方案,但许多工程师在实际操作…...
别再手动记数据了!组态王Kingview 7.5 SP6搭配Access数据库,实现工业数据自动存储与查询
工业数据自动化管理实战:组态王与Access的高效联动方案 在工业现场,数据采集与记录是保障生产稳定运行的基础环节。传统的手工记录方式不仅效率低下,还容易因人为因素导致数据错漏。我曾在一家化工厂亲眼目睹操作员因记录笔误导致整批生产参数…...
ai生成代码如何管理?快马结合gitbash实现智能开发工作流
今天想和大家分享一个高效的工作流:如何用AI生成代码后,通过GitBash进行规范的版本管理。最近在InsCode(快马)平台实践了这个方法,整个过程非常流畅。 AI生成代码阶段 在快马的AI对话区输入需求:“创建一个带有深色模式切换功能的…...
