Spring bean的生命周期和扩展
接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,以具体实例看bean生命周期的一些执行阶段
bean生命周期流程
| 生命周期 | 扩展处理 | 说明 |
| 实例化:createBeanInstance | 构造方法, 如@Autowired的构造方法注入依赖bean | 如UserService构造方法注入AppDAO: |
| 属性设置:populateBean | 如setter方法注入的依赖 如@Autoware的filed注入 | 如UserService中注入UserDAO: |
| 初始化:initializeBean | 1. BeanPostProcessor#postProcessBeforeInitialization 2. @PostConstruct 3. InitializingBean#afterPropertiesSet initMethod 4. BeanPostProcessor#postProcessAfterInitialization | 上一步骤属性设置完后,初始化方法前后都可以扩展。 例如BeanPostProcessor#postProcessBeforeInitialization,直接改变了set注入的appDAO对象 |
| 销毁 | 1. @PreDestroy 2. DisposableBean#destroy destroyMethod |
附org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
/*** Actually create the specified bean. Pre-creation processing has already happened* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.* <p>Differentiates between default bean instantiation, use of a* factory method, and autowiring a constructor.* @param beanName the name of the bean* @param mbd the merged bean definition for the bean* @param args explicit arguments to use for constructor or factory method invocation* @return a new instance of the bean* @throws BeanCreationException if the bean could not be created* @see #instantiateBean* @see #instantiateUsingFactoryMethod* @see #autowireConstructor*/protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}
扩展执行
接上文:AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,来看这些BeanPostProcessor如何起作用
测试bean定义类如下
@Service("userService")
public class UserService implements InitializingBean, DisposableBean {private String userServiceName;private UserDAO userDAO;private AppDAO appDAO;/*** field 注入*/@Autowiredprivate CommonService commonService;public UserService() {System.out.println("constructor");}/*** 类似于 InitializingBean 的 afterPropertiesSet() 方法*/@PostConstructpublic void init() {System.out.println("PostConstruct userService");System.out.println("userDAO is not null:" + (userDAO != null));System.out.println("appDAO is not null:" + (appDAO != null));userServiceName = "selfUserService";}/*** setter注入* @param userDAO*/@Resource(name = "u")public void setUserDAO(UserDAO userDAO) {System.out.println("setUserDAO:" + userDAO);this.userDAO = userDAO;}/*** 构造器注入* @param appDAO*/@Autowiredpublic UserService(AppDAO appDAO) {System.out.println("@Autowired appDAO:" + appDAO);this.appDAO = appDAO;}public void add(User user) {userDAO.save(user);}public UserDAO getUserDAO() {return userDAO;}/*** 类似于 DisposableBean 的 destroy() 方法*/@PreDestroypublic void preDestroy() {System.out.println("preDestroy");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("afterPropertiesSet userService");}@Overridepublic void destroy() throws Exception {System.out.println("destroy userService");}public void setUserServiceName(String userServiceName) {this.userServiceName = userServiceName;}public void setAppDAO(AppDAO appDAO) {this.appDAO = appDAO;}@Overridepublic String toString() {return "UserService{" +"userServiceName='" + userServiceName + '\'' +", userDAO=" + userDAO +", appDAO=" + appDAO +", commonService=" + commonService +'}';}
}
InstantiationAwareBeanPostProcessors:SmartInstantiationAwareBeanPostProcessor
推断构造函数,最后是AutowiredAnnotationBeanPostProcessor完成构造函数的推断

最后判断有@Autowired的构造函数 完成实例化过程
InstantiationAwareBeanPostProcessor:CommonAnnotationBeanPostProcessor
populate阶段CommonAnnotationBeanPostProcessor完成setter注入
/*** setter注入* @param userDAO*/
@Resource(name = "u")
public void setUserDAO(UserDAO userDAO) {System.out.println("setUserDAO:" + userDAO);this.userDAO = userDAO;
}
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties
@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);try {metadata.inject(bean, beanName, pvs);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);}return pvs;}
InstantiationAwareBeanPostProcessor:AutowiredAnnotationBeanPostProcessor
populate阶段AutowiredAnnotationBeanPostProcessor完成@Autorwired的filed的注入,具体可以再次阅读:Spring5.1.3 @Autorwired注解原理重新回顾-CSDN博客
BeanPostProcessor#postProcessBeforeInitialization
initializeBean阶段会执行BeanPostProcessor的postProcessBeforeInitialization方法
执行自定义的BeanPostProcessor

执行CommonAnnotationBeanPostProcessor解析@PostConstruct注解

@PostConstruct
public void init() {System.out.println("PostConstruct userService");System.out.println("userDAO is not null:" + (userDAO != null));System.out.println("appDAO is not null:" + (appDAO != null));userServiceName = "selfUserService";
}
执行InitializingBean的afterPropertiesSet方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isTraceEnabled()) {logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) {try {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {((InitializingBean) bean).afterPropertiesSet();}}if (mbd != null && bean.getClass() != NullBean.class) {String initMethodName = mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) &&!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.isExternallyManagedInitMethod(initMethodName)) {invokeCustomInitMethod(beanName, bean, mbd);}}}
BeanPostProcessor#postProcessAfterInitialization
InitializingBean最后阶段会执行BeanPostProcessor的postProcessAfterInitialization方法
本例
@Component
public class ServiceBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// Bean 初始化前的逻辑if (beanName.equals("userService")) {UserService userService = (UserService)bean;AppDAO appDAO = new AppDAOImpl2();userService.setAppDAO(appDAO);System.out.println("postProcessBeforeInitialization:" + ":" + bean);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// Bean 初始化后的逻辑if (beanName.equals("userService")) {System.out.println("postProcessAfterInitialization:" + ":" + bean);}return bean;}
}

相关文章:
Spring bean的生命周期和扩展
接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,以具体实例看bean生命周期的一些执行阶段 bean生命周期流程 生命周期扩展处理说明实例化:createBeanInstance 构造方法, 如Autowired的构造方法注入依赖bean 如UserSer…...
计算机网络 (33)传输控制协议TCP概述
一、定义与基本概念 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它工作在OSI模型的第四层,即传输层,为用户提供可靠的、有序的和无差错的数据传输服务。TCP协议与UDP协议是传输层的两大主要协议,但两者在设计上有明显的不同&…...
Python3 JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript编程语言的一个子集,但JSON是独立于语言的,很多编程语言都支持JSON格式数据的…...
Leetcode 698 Partition to K Equal Sum Subsets
题意 给一个数组,要求把数组里的元素分成k个子集,满足每个子集中数的总和是相等的。问是否能分成k个子集 题目链接 https://leetcode.com/problems/partition-to-k-equal-sum-subsets/description/ 思考 想象你有k个桶,然后你有n个小球&…...
可靠的人形探测,未完待续(III)
一不小心,此去经年啊。问大家新年快乐! 那,最近在研究毫米波雷达模块嘛,期望用在后续的产品中,正好看到瑞萨的活动送板子,手一下没忍住。 拿了板子就得干活咯,我一路火花带闪电,开整…...
Git文件夹提交错了,怎么撤销?
最近提交了一些不应该提交的文件夹到git中,现在需要移除它们,现在简单记录一下操作日志: 情况一 文件夹已经被添加到 Git,但未提交 如果文件夹已经被 git add 添加到暂存区中,但尚未提交,你可以使用以下命令将其从暂存区中移除: git rm -r …...
小程序textarea组件键盘弹起会遮挡住输入框
<textarea value"{{remark}}" input"handleInputRemark" ></textarea> 如下会有遮挡: 一行代码搞定 cursor-spacing160 修改后代码 <textarea value"{{remark}}" input"handleInputRemark" cursor-spacin…...
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例 1.代码在/kernel-5.10文件夹下 2.在kernel-5.10目录下执行如下命令编译 : 编译之前,需要将 clang 导出到 PATH 环境变量: 如果是 Android12 执行下面这条命令 export PATH../pr…...
qt 窗口(window/widget)绘制/渲染顺序 QPainter QPaintDevice Qpainter渲染 失效 无效
qt窗体布局 窗体渲染过程 qt中窗体渲染逻辑顺序为 本窗体->子窗体/控件 递归,也就是说先渲染父窗体再渲染子窗体。其中子窗体按加入时的先后顺序进行渲染。通过下方的函数调用堆栈可以看出窗体都是在widget组件源码的widgetprivate::drawwidget中进行渲染的&am…...
Ubuntu下载时不显示无线网图标并显示Cable unplugged
我用的是ubuntu22-04-5.iso一下载出来发现无法连接网络甚至直接显示Wired是Cable unplugged. 下面是解决方法: step1: step2:点击编辑中的虚拟网络编辑器 step3: step4: step5: step6:取消勾选自动检测可用的DNS服务器 step7:在window上按下winR输入c…...
微信小程序实现人脸识别登录
hello hello~ ,这里是 code袁~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 🦁作者简介:一名喜欢分享和记录学习的在校大学生…...
atoi函数的概念和使用案例
atoi 函数是 C 语言标准库中的一个函数,它用于将字符串转换为整数。atoi 的名称是 “ASCII to integer” 的缩写。该函数定义在 <stdlib.h> 头文件中。 概念 atoi 函数会从字符串的开始位置开始转换,直到遇到第一个非数字字符或遇到字符串结束符…...
Mysql--运维篇--日志管理(连接层,SQL层,存储引擎层,文件存储层)
MySQL提供了多种日志类型,用于记录不同的活动和事件。这些日志对于数据库的管理、故障排除、性能优化和安全审计非常重要。 一、错误日志 (Error Log) 作用: 记录MySQL服务器启动、运行和停止期间遇到的问题和错误信息。 查看: 默认情况下…...
poi处理多选框进行勾选操作下载word以及多word文件压缩
一、场景 将数据导出word后且实现动态勾选复选框操作 eg: word模板 导出后效果(根据数据动态勾选复选框) 二、解决方案及涉及技术 ① 使用poi提供的库进行处理(poi官方文档) ② 涉及依赖 <!-- excel工具 --><depen…...
QT 键值对集合QMap
在QT中,可以使用QMap作为键值对的集合。QMap是Qt的一个模板类,它存储了键值对,并且可以通过键来快速查找值。 导入 #include <QMap> 以下是一些使用QMap的方法: 1.创建并初始化一个 QMap<int, QString> UserDepa…...
NetMQ里Push-Pull模式,消息隔一收一问题小记
问题: 本机环境下,在push端向pull端发送消息的过程中,发现同一个进程里的pusher和puller代码,可以准确地完成收发; 然而,将代码放在两个进程里,将pusher发送的消息从1计数,puller端竟…...
见微知著:Tripo 开创 3D 生成新时代
关于 VAST VAST 成⽴于 2023 年 3 ⽉,是⼀家致⼒于通⽤ 3D 大模型研发的 AI 公司,公司⽬标是通过打造⼤众级别的 3D 内容创作⼯具,建⽴ 3D 的 UGC 内容平台,让基于 3D 的空间成为⽤户体验、内容表达、提升新质⽣产⼒的关键要素。 2024 年初,VAST 推出数⼗亿参数级别的 3…...
消息队列与中间件:Java的秘密传输带
消息队列与中间件技术是分布式系统中的重要组件,它们主要解决应用耦合、异步消息处理、流量削峰等问题,并实现高性能、高可用、可伸缩和最终一致性的架构。 2.1 消息队列的基本概念 消息队列是一种应用程序间传递消息的技术,它允许应用程序发…...
Bytebase 3.1.0 - 通过 Google / GitHub SSO 功能开放给专业版
🚀 新功能 支持在 PostgreSQL DML/DDL 工单中选择执行角色。 在项目设置中增加 PostgreSQL 数据库租户模式配置选项。 在数据库页面和 SQL 编辑器为 ORACLE 数据库展示 package 元数据。 支持为环境配置颜色,方便区分。 新增管理员可关闭数据导出…...
EdgeOne安全专项实践:上传文件漏洞攻击详解与防范措施
靶场搭建 当我们考虑到攻击他人服务器属于违法行为时,我们需要思考如何更好地保护我们自己的服务器。为了测试和学习,我们可以搭建一个专门的靶场来模拟文件上传漏洞攻击。以下是我搭建靶场的环境和一些参考资料,供大家学习和参考࿰…...
SMT波浪焊接工艺精准控制品质核心
SMT波浪焊接过程中,设备是基础,而工艺参数的精准控制则是决定焊接质量的核心。很多电子制造企业都会遇到这样的问题:同样的设备、同样的原材料,不同批次的产品焊接质量却参差不齐,有的焊点牢固、外观规整,有…...
保姆级教程:用sw_urdf_exporter插件将Solidworks机械臂模型转为ROS可用的URDF
从Solidworks到ROS:机械臂URDF转换全流程实战指南 机械臂作为工业自动化和服务机器人的核心部件,其运动仿真在ROS生态中占据重要地位。许多工程师习惯使用Solidworks进行机械结构设计,却苦于如何将设计成果无缝迁移到ROS环境。本文将彻底解决…...
2025最权威的AI论文助手推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在当下诸多处于主流地位的AI论文工具当中,Grammarly于语法校对以及学术表达优化…...
【光学】基于matlab偏振光线追迹【含Matlab源码 15265期】
💥💥💥💥💥💥💞💞💞💞💞💞💞💞欢迎来到海神之光博客之家💞💞💞Ὁ…...
突破Windows与Android壁垒:APK-Installer重构跨平台应用安装体验
突破Windows与Android壁垒:APK-Installer重构跨平台应用安装体验 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 在数字化生活中,两个场景常常困…...
别再只盯着Logits了!聊聊知识蒸馏里‘注意力图’那点事儿(从AT论文到理解误区)
注意力蒸馏:超越Logits的知识迁移新范式 在深度学习模型压缩领域,知识蒸馏早已不是新鲜话题。大多数实践者会条件反射地想到教师网络输出的logits或中间层特征——这些确实是最直观的知识载体。但当我们把目光投向人类的学习过程时,会发现一个…...
突破网盘限速:2025年开源直链解析工具实用指南
突破网盘限速:2025年开源直链解析工具实用指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / …...
芯片研发为什么总是延期?问题不在技术,在管理没闭环
一个芯片项目失败,事后复盘,技术问题往往只占一小部分。更多的时候,是计划没做好,执行过程没人盯,出了问题没人协调,最后交付的时候才发现跑偏了很久。这是行业里非常普遍的现象。法约尔在一百年前提出管理…...
汽车电子电气架构演进:从分布式 ECU 到中央计算平台
目录 一、电子电气架构的六大演进阶段 二、高性能处理器与软件平台重构 三、宝马分层式电子电气架构设计 四、中央通信服务器与可扩展网络 五、车云一体架构与软件开发变革 六、架构升级代码示例:SOA 服务注册与调用 七、中央计算平台配置示例(代码…...
千万级日志清洗仅需11秒:Polars 2.0流式分块+并行UDF实战(附可复用清洗模板库)
第一章:千万级日志清洗仅需11秒:Polars 2.0流式分块并行UDF实战(附可复用清洗模板库)传统Pandas在处理千万级Nginx或Kafka日志时,常因内存暴涨与单线程瓶颈导致清洗耗时超3分钟。Polars 2.0引入的scan_csv()流式扫描 …...
