尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Spring Bean 生命周期源码分析:实例化、初始化、后置处理器与销毁
如果这篇文章对你有帮助欢迎关注我的CSDN账号「来福猿」 有问题可以在评论区留言我会一一回复。一、为什么要深入理解 Bean 生命周期Spring 容器最核心的能力就是帮我们管理对象的创建、依赖注入、初始化与销毁。很多开发者平常用Component、Autowired时并不会刻意关心背后发生了什么但一旦接触到 AOP、事务、配置动态刷新、循环依赖或者资源泄漏排查Bean 生命周期就会成为绕不过去的一道坎。理解 Bean 生命周期至少有四个实际收益第一能看懂BeanPostProcessor为什么可以代理对象从而理解 AOP 的实现基础第二能区分PostConstruct、InitializingBean和自定义init-method的先后顺序避免初始化逻辑写在错误的位置第三能正确释放数据库连接、线程池、文件句柄等资源防止内存泄漏第四能在面试或源码阅读时快速定位AbstractAutowireCapableBeanFactory中的关键方法。本文以 Spring 5.x/6.x 的核心源码AbstractAutowireCapableBeanFactory为主线把 Bean 生命周期拆成实例化、属性填充、初始化、销毁四个阶段配合可运行的示例代码逐一分析。二、Bean 生命周期全景流程先建立整体印象。一个单例 Bean 从无到有、再到销毁大致经过下面这条链路flowchart TD A[读取 BeanDefinition] -- B[createBeanInstance 实例化] B -- C[populateBean 属性填充] C -- D[initializeBean 初始化] D -- E[放入单例池 使用中] E -- F[容器关闭 close] F -- G[destroy 销毁回调]其中initializeBean内部又隐藏了一条更细的顺序链也是最容易被问到的部分flowchart TD A[initializeBean] -- B[invokeAwareMethods 回调 Aware 接口] B -- C[BeanPostProcessor before 前置处理] C -- D[InitializingBean.afterPropertiesSet] D -- E[自定义 init-method] E -- F[BeanPostProcessor after 后置处理] F -- G[Bean 就绪]下面我们沿着这条主线逐个阶段看源码。三、阶段一Bean 实例化3.1 createBeanInstance创建 Bean 的入口实例化解决的是「调用哪个构造方法或工厂方法把对象创建出来」的问题这一步还没有做属性注入。核心代码在AbstractAutowireCapableBeanFactory#createBeanInstance中其决策顺序可以概括为如果BeanDefinition提供了Supplier直接调用Supplier.get()创建实例如果配置了工厂方法factoryMethod通过反射调用该静态或实例工厂方法创建如果存在已解析的构造器缓存直接使用缓存的构造器创建否则进入构造器推断determineConstructorsFromBeanPostProcessors交给SmartInstantiationAwareBeanPostProcessor选择合适的构造器仍然无法推断时回退到默认无参构造方法实例化。源码主流程可简化为protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { Class? beanClass resolveBeanClass(mbd, beanName); // 1. Supplier 优先 Supplierlt;?gt; instanceSupplier mbd.getInstanceSupplier(); if (instanceSupplier ! null) { return obtainFromSupplier(instanceSupplier, beanName); } // 2. 工厂方法 if (mbd.getFactoryMethodName() ! null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 3. 构造器推断 Constructorlt;?gt;[] ctors determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors ! null) { return autowireConstructor(beanName, mbd, ctors, args); } // 4. 默认无参构造 return instantiateBean(beanName, mbd); }3.2 实例化前后插手的 PostProcessor在真正调用构造方法前后InstantiationAwareBeanPostProcessor提供了两个拦截点postProcessBeforeInstantiation在实例化之前调用如果返回值不为nullSpring 会直接使用这个返回值作为 Bean跳过默认实例化流程AOP 代理的提前创建就与此有关postProcessAfterInstantiation在实例化完成、属性填充之前调用返回false可以阻止后续属性填充。这一阶段只是「把对象造出来」字段里的Autowired依赖还没有被注入下一阶段才处理依赖。四、阶段二属性填充实例化得到的是一个「空壳」对象接下来populateBean负责把配置文件、注解中的依赖值注入进去protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { // 1. 再次给 InstantiationAwareBeanPostProcessor 拦截机会 if (!mbd.isSynthetic() hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } // 2. 按 AUTOWIRE_BY_NAME / AUTOWIRE_BY_TYPE 自动注入 if (mbd.getResolvedAutowireMode() AUTOWIRE_BY_NAME || AUTOWIRE_BY_TYPE) { autowireByName(...); autowireByType(...); } // 3. 处理 Autowired、Value、Inject 等注解注入 for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); } // 4. 最终把属性值写入 Bean applyPropertyValues(beanName, mbd, bw, pvs); }这里有一个关键细节Autowired注解并不是由核心 BeanFactory 直接处理的而是通过AutowiredAnnotationBeanPostProcessor这个InstantiationAwareBeanPostProcessor在postProcessProperties中完成注入。这也是为什么把Autowired称为「后置处理器驱动的注入机制」。五、阶段三初始化属性注入完成后对象在业务上已经可以工作但 Spring 还提供了一整套「初始化钩子」让用户或框架有机会做进一步的定制。这条链路的入口是initializeBean需要牢记其内部顺序。5.1 第一步Aware 接口回调invokeAwareMethods会依次回调三个Aware接口BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。如果你的 Bean 实现了这些接口就能拿到自身名称、类加载器和所属工厂的引用。除此之外的EnvironmentAware、ApplicationContextAware等则由ApplicationContextAwareProcessor等专门的处理器完成回调原理类似。5.2 第二步BeanPostProcessor 前置处理接下来遍历所有BeanPostProcessor调用postProcessBeforeInitialization。PostConstruct注解就是通过InitDestroyAnnotationBeanPostProcessor在此时执行的public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) { Object result existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current processor.postProcessBeforeInitialization(result, beanName); if (current null) { return result; } result current; } return result; }5.3 第三步InitializingBean.afterPropertiesSet如果 Bean 实现了InitializingBean接口invokeInitMethods会调用它的afterPropertiesSet()。紧接着如果BeanDefinition上配置了自定义init-methodXML 中的init-method属性或注解方式Bean(initMethod ...)也会在此后通过反射执行。protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd) { // 1. InitializingBean 接口回调 if (bean instanceof InitializingBean) { ((InitializingBean) bean).afterPropertiesSet(); } // 2. 自定义 init-method String initMethodName mbd.getInitMethodName(); if (initMethodName ! null !(bean instanceof InitializingBean afterPropertiesSet.equals(initMethodName))) { invokeCustomInitMethod(beanName, bean, mbd); } }5.4 第四步BeanPostProcessor 后置处理初始化方法执行完毕后Spring 会再次遍历BeanPostProcessor调用postProcessAfterInitialization。这是整个生命周期中「动手脚」最频繁的位置AbstractAutoProxyCreator就在这里为 Bean 创建 AOP 代理。所以你最终通过getBean拿到的对象很可能已经不是最初实例化的那个对象了。把初始化阶段完整串起来就是下面这张图flowchart LR A[Aware 回调] -- B[BeanPostProcessor before / PostConstruct] B -- C[afterPropertiesSet] C -- D[自定义 init-method] D -- E[BeanPostProcessor after / AOP 代理]六、后置处理器体系详解理解了上面的流程再看后置处理器家族会更清晰。它们虽然名字里都带 PostProcessor但介入时机完全不同容易混淆处理器类型核心接口介入时机典型用途BeanFactoryPostProcessorBeanFactoryPostProcessor容器启动阶段Bean 实例化之前修改 BeanDefinition、属性占位符替换、配置中心刷新BeanPostProcessorBeanPostProcessor每个 Bean 初始化前后日志、校验、AOP 代理创建InstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessor实例化前后、属性填充前后替代默认构造、注解注入、循环依赖处理DestructionAwareBeanPostProcessorDestructionAwareBeanPostProcessorBean 销毁之前释放资源、清除缓存、PreDestroy回调一个容易背错的顺序是BeanFactoryPostProcessor操作的是「Bean 的定义」发生在任何 Bean 实例化之前而BeanPostProcessor操作的是「Bean 的实例」发生在每个 Bean 的初始化阶段。两者作用对象不同不能混为一谈。七、阶段四销毁7.1 destroy-method 的执行顺序当容器调用close()关闭时单例 Bean 会依次走销毁流程。其执行顺序与初始化基本对称先执行PreDestroy再执行DisposableBean.destroy()最后执行自定义destroy-method。flowchart TD A[容器 close] -- B[DestructionAwareBeanPostProcessor before / PreDestroy] B -- C[DisposableBean.destroy] C -- D[自定义 destroy-method] D -- E[资源释放完成]7.2 registerDisposableBeanIfNecessaryBean 是否在容器关闭时被销毁取决于创建流程末尾的registerDisposableBeanIfNecessary。当 Bean 实现了DisposableBean、配置了destroy-method、或者被DestructionAwareBeanPostProcessor标记为需要销毁时Spring 会将其封装成DisposableBeanAdapter并注册到容器的disposableBeans缓存中关闭容器时统一回调。八、源码主流程串讲doCreateBean把上面四个阶段合并起来就得到了 Spring 创建 Bean 的「总导演」AbstractAutowireCapableBeanFactory#doCreateBean核心逻辑如下protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) { // 1. 实例化创建空的 Bean 实例 BeanWrapper instanceWrapper createBeanInstance(beanName, mbd, args); Object bean instanceWrapper.getWrappedInstance(); // 2. 属性填充完成依赖注入 populateBean(beanName, mbd, instanceWrapper); // 3. 初始化Aware 回调、before、init 方法、after Object exposedObject initializeBean(beanName, bean, mbd); // 4. 注册销毁回调 registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject; }而initializeBean又把初始化阶段串了起来protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) { // 1. Aware 接口回调 invokeAwareMethods(beanName, bean); // 2. 前置处理PostConstruct 在此执行 Object wrappedBean applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 3. 初始化方法afterPropertiesSet 自定义 init-method invokeInitMethods(beanName, wrappedBean, mbd); // 4. 后置处理AOP 代理在此创建 wrappedBean applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); return wrappedBean; }记住这条调用链面试中被问到「请描述 Spring Bean 的生命周期」时基本就能把每个阶段和对应的源码方法一一对应起来了。九、完整可运行示例下面用一个注解方式启动的 Spring 应用把整个生命周期按顺序打印出来方便对照验证import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; public class BeanLifecycleDemo { public static void main(String[] args) { AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class); System.out.println( 容器启动完成开始使用 Bean ); UserService userService context.getBean(UserService.class); userService.sayHello(); context.close(); System.out.println( 容器已关闭 ); } Configuration static class AppConfig { Bean(initMethod customInit, destroyMethod customDestroy) public UserService userService() { return new UserService(); } Bean public MyBeanPostProcessor myBeanPostProcessor() { return new MyBeanPostProcessor(); } } static class UserService implements InitializingBean, DisposableBean { public UserService() { System.out.println(1. 构造方法Bean 实例化); } public void customInit() { System.out.println(4. 自定义 init-methodcustomInit()); } Override public void afterPropertiesSet() { System.out.println(3. InitializingBean.afterPropertiesSet()); } public void sayHello() { System.out.println(业务方法sayHello()); } public void customDestroy() { System.out.println(7. 自定义 destroy-methodcustomDestroy()); } Override public void destroy() { System.out.println(6. DisposableBean.destroy()); } } static class MyBeanPostProcessor implements BeanPostProcessor { Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof UserService) { System.out.println(2. BeanPostProcessor.postProcessBeforeInitialization()); } return bean; } Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof UserService) { System.out.println(5. BeanPostProcessor.postProcessAfterInitialization()); } return bean; } } }运行后控制台输出如下顺序与前面的源码分析完全一致1. 构造方法Bean 实例化 2. BeanPostProcessor.postProcessBeforeInitialization() 3. InitializingBean.afterPropertiesSet() 4. 自定义 init-methodcustomInit() 5. BeanPostProcessor.postProcessAfterInitialization() 容器启动完成开始使用 Bean 业务方法sayHello() 6. DisposableBean.destroy() 7. 自定义 destroy-methodcustomDestroy() 容器已关闭 十、常见面试题与易错点初始化顺序构造方法 → 属性注入 →PostConstruct→afterPropertiesSet→ 自定义init-method不要记反PostConstruct本质上是靠BeanPostProcessor的前置方法执行的。拿到的 Bean 可能被替换postProcessAfterInitialization返回的对象会替换原对象这也是 AOP 代理 Bean 的由来如果处理器返回nullSpring 会保留原对象。BeanFactoryPostProcessor 与 BeanPostProcessor 的区别前者改定义、在实例化前执行后者改实例、在初始化前后执行。为什么构造器注入能部分避免循环依赖循环依赖的自动解围依赖「先实例化、再填充」的两段式创建构造器注入在实例化阶段就要求依赖因此无法靠三级缓存直接解围。销毁方法不会自动处理所有资源只有注册到DisposableBeanAdapter的销毁逻辑才会在close()时执行prototype作用域的 Bean 通常不由容器负责完整销毁需要调用方自行管理。十一、总结Spring Bean 的生命周期可以概括为「两创建、两加工」createBeanInstance完成实例化populateBean完成依赖注入initializeBean完成初始化回调与后置加工最后在容器关闭时通过dispose链路完成销毁。整条链路的横切扩展能力都来自不同阶段的PostProcessor这也是 Spring 框架高度可插拔的根本原因。建议读者把AbstractAutowireCapableBeanFactory#doCreateBean作为阅读入口配合本文的示例代码在本地断点调试一遍。把调用栈实际走一次比单纯背诵顺序要可靠得多。
RELATED

相关推荐

Agent评测 G-Eval论文分析

Agent评测 G-Eval论文分析

本文采用部分原文翻译个人结合AI解读的 https://arxiv.org/pdf/2303.16634 文章目录G-EVAL: NLG Evaluation using GPT-4 with Better Human AlignmentAbstract1. Introduction2. MethodPrompt for NLG EvaluationAuto Chain-of-Thoughts for NLG EvaluationScoring Function3…

📅 2026/10/9 13:55:20
当自然语言遇上数据库:Text2Sql.Net的MCP革命如何重新定义开发者与数据的交互方式|TaoToken 统一 Key 实战

当自然语言遇上数据库:Text2Sql.Net的MCP革命如何重新定义开发者与数据的交互方式|TaoToken 统一 Key 实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/9 13:55:20
Manus联合创始人拆解:Claude与阿里千问双模型驱动下的TaoToken统一API接入实践

Manus联合创始人拆解:Claude与阿里千问双模型驱动下的TaoToken统一API接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/9 13:55:20
MORE NEWS

更多资讯

📰

数据库原理复习链路:往年卷拆解、SQL作业与课设避坑指南

简介:面向天津大学「数据库应用(原理)」课程的备考者与自学者,资源包集中整理往年试卷、课程大作业与实验报告,内容覆盖SQL语言、关系数据库模型、数据完整性、事务处理、索引构建与查询优化等核心考点,并包…

📰

虚谷数据库迁移工具Windows 64位实战:类型映射、字符集与避坑指南

简介:虚谷数据库迁移工具(Windows 64位)是一款面向数据库管理员与系统运维人员的迁移辅助软件,用于在跨平台或跨版本场景下完成数据搬迁与系统升级,尤其适合从旧数据库替换到新环境或更换数据库管理系统时的数据保障。…

📰

数据库物理模型设计实战:从建表、索引到分区与压测避坑指南

简介:这份文档面向数据库设计初学者与需要梳理建模思路的开发者,聚焦数据库物理模型设计这一关键环节,讲解如何在实际存储系统中落地逻辑模型,以兼顾性能、存储效率与数据管理。内容以四种核心设计模式为主线,重点展开…

📰

银行卡BIN数据实战:从Excel清洗到MySQL查询与风控应用

简介:这套银行卡BIN数据基于银联官方2020年4月25日发布的最新版本整理,共涵盖9868条记录,字段包含银行卡bin、bin长度、发卡行、银行卡名、银行卡类型、银行卡长度等核心信息,适合支付系统开发、金融风控、账户校验、渠道对账等场…

📰

mysql.zip题库导入实战:识别、导入、查题与API封装

简介:面向在线K12教育从业者与题库系统开发人员,这份MySQL数据库资源包围绕数学、物理、化学公式的录入和显示这一在线教育常见痛点,完整演示了试题存储、LaTeX公式渲染、知识点章节建设、题目属性设置等核心环节,并附带可参考的样…

📰

CCNP PDF课程资料学习指南:从理论基础到实验验证的网络工程师进阶路线

简介:思科CCNP课程.pdf是一份根据培训机构内部PPT整理而成的CCNP学习笔记,作者边看边记,适合备考CCNP或负责企业级网络设计、实施与排障的网络工程师。内容覆盖TCP/IP协议回顾、VLAN/Trunk/VTP部署、生成树STP与RSTP、二层与三层交换、链路聚…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬