尧图网络 高端网站定制 · 原创设计
免费咨询热线
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/26 13:18:05
当自然语言遇上数据库: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/26 8:22:46
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/11/7 21:30:26
MORE NEWS

更多资讯

📰

清远电工证复审机构的真实经历:电工证复审不搞虚的,这几点你得知道

清远电工证复审机构的真实经历:电工证复审不搞虚的,这几点你得知道 你是不是正为找工作发愁?是不是还在为没有特种作业证而四处碰壁?别急,我来告诉你一个 真实经历 :去年我一个老乡,本来已经找好了电工的工作,结果因为电工证 没及时复审…

📰

高考需要电工证吗?郑州报考避坑指南教你避开实操考试心里没底怕挂科

高考需要电工证吗?郑州报考避坑指南教你避开实操考试心里没底怕挂科 实操考试心里没底怕挂科?你不是一个人。每年郑州成千上万的考生和考生家长都在问: 高考需要电工证吗…

📰

工地太忙根本没时间复习考试?电工证办理最快途径让你轻松上岗必备

工地太忙根本没时间复习考试?电工证办理最快途径让你轻松上岗必备 工地太忙根本没时间复习考试,这几乎是每个施工现场管理人员都面临的问题。尤其在项目赶工期、任务重的情况下,很多电工操作人员甚至管理人员都忽略了“电工证办理最快途径”这一关键点。实…

📰

福州应急电工证怎么考不被坑?网上查询报名全攻略

福州应急电工证怎么考不被坑?网上查询报名全攻略 你是不是还在为福州应急电工证怎么考发愁?是不是怕被中介骗钱?别急,这篇文章教你一步步走稳流程,避免踩坑。现在就能 网上查询 官方报名入口,安全、透明、靠谱。 一、福州应急电工证报考流程全解析…

📰

电工证考试主播怎么选?郑州报考避坑指南看这里

电工证考试主播怎么选?郑州报考避坑指南看这里 之前考的证在外省能不能转过来?这是很多电工证考试主播、一线作业人员最关心的问题之一。尤其是像信阳浉河区从事公路工程的师傅,经常在多个省市项目间奔波,证照转接成了刚需。如果你正准备报考电工证考试主…

📰

电工证可以从事的行业保姆级教程:新手必看的就业方向和报考指南

电工证可以从事的行业保姆级教程:新手必看的就业方向和报考指南 你现在手里还拿着电工证吗?有没有遇到过这种情况:拿着电工证,却不知道能去哪家公司上班?别急,这篇文章就是专门为你写的。 急需特种作业证才能上岗找工作…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬