《Java 100 天进阶之路》第74篇:Bean生命周期(2026版)
2026/9/1 11:15:49 网站建设 项目流程

第74篇:Bean生命周期(2026版)

📌系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第73篇:Spring IoC容器 |
➡️ 下一篇:第75篇:Spring AOP原理

🗺️ 本文阅读地图(3 分钟速览)

第73篇搞定了IoC容器的概念,本篇深入Bean生命周期。很多开发者用了多年Spring,只停留在@Autowired注入Bean的表层,一旦遇到Bean初始化顺序异常、循环依赖报错、扩展点执行不符合预期等问题,就无从下手。搞懂Bean生命周期,就是搞懂了Spring IoC容器的核心灵魂

Spring全家桶专题持续推进,拿下AOP!

《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇,建议收藏 + 关注,一起100天拿offer!

👉 点击关注我,更新后第一时间收到推送!

模块核心问题一句话回答
生命周期是什么Bean从生到死经历什么?实例化 → 属性填充 → 初始化 → 使用 → 销毁
实例化Bean对象怎么创建的?容器通过反射调用构造函数创建Bean实例
属性填充依赖怎么注入的?容器通过依赖注入为Bean设置属性值
初始化初始化阶段做了哪些事?Aware回调 → BeanPostProcessor前置 → 初始化方法 → BeanPostProcessor后置
Aware接口Bean怎么感知容器?实现BeanNameAwareBeanFactoryAware等接口,容器自动回调
BeanPostProcessor怎么在初始化前后插一脚?实现postProcessBeforeInitializationpostProcessAfterInitialization
销毁Bean怎么被销毁?容器关闭时,执行@PreDestroyDisposableBean.destroy()→ 自定义destroy-method
面试最爱问高频考点有哪些?见文末 面试小节

一、核心知识点

1. 什么是Bean生命周期?

Bean的生命周期指的是一个Bean从创建到销毁的完整过程。Spring IoC容器会按照固定的流程,完成Bean的实例化、属性注入、初始化、销毁全生命周期管控。

💡普通对象 vs Bean:普通Java对象通过new关键字手动实例化,生命周期仅与JVM垃圾回收相关;Spring Bean由IoC容器统一管理,容器提供了大量可插拔的扩展点,允许开发者在生命周期的任意节点介入。普通对象的命运握在开发者手里,Bean的命运握在Spring容器手里

2. 为什么需要了解Bean生命周期?

价值说明
问题排查遇到初始化异常、依赖注入问题时,能快速定位问题阶段
功能扩展通过BeanPostProcessor等扩展点实现AOP、属性加密等高级功能
性能优化了解各阶段执行时机,避免在初始化阶段执行耗时操作
架构设计开发Spring生态中间件时,必须充分理解生命周期才能正确集成

3. 谁在管理Bean的生命周期?

Spring中负责管理Bean生命周期的核心类是AbstractAutowireCapableBeanFactory。它定义了创建Bean的模板方法——实例化、属性填充、初始化的顺序固定,但具体步骤可以被子类扩展。


二、通俗讲解(1分钟开心学)

把Bean的生命周期想象成"员工入职流程"

这个比喻来自网络上的经典总结,非常形象:

  • ① 实例化:公司(Spring容器)根据简历(BeanDefinition)发出Offer,员工来报到——分配工位(分配内存),人进来了,但电脑、工牌都还没配。
  • ② 属性填充:HR给员工配电脑、工牌、门禁卡——这就是依赖注入,把需要的"装备"(依赖的其他Bean)配齐。
  • ③ Aware回调:员工认识一下公司环境——知道自己的工号(BeanNameAware)、知道HR部门在哪(BeanFactoryAware)、知道公司在几号楼(ApplicationContextAware)。
  • ④ BeanPostProcessor前置处理:入职体检——在正式上岗前做一次检查。
  • ⑤ 初始化:参加新员工培训(@PostConstruct)、签劳动合同(InitializingBean.afterPropertiesSet())、领工服(自定义init-method)。
  • ⑥ BeanPostProcessor后置处理:发放工作证——AOP动态代理就是在这里创建的
  • ⑦ 使用:正式上岗干活。
  • ⑧ 销毁:离职交接——还电脑(@PreDestroy)、办离职手续(DisposableBean.destroy())、注销工号(自定义destroy-method)。

三、Bean生命周期完整流程(15步)

一个完整的Spring Bean生命周期可以分为四大阶段、15个关键步骤


四、各阶段深度拆解

4.1 实例化阶段(Instantiation)

容器通过反射机制调用构造函数创建Bean的实例。这是生命周期的起点。

💡实例化 ≠ 初始化:实例化只是"把人招进来、工位分配好",但电脑、工牌都还没配。属性填充和初始化才是"配装备、做培训"。

4.2 属性填充阶段(Populate Properties)

容器通过依赖注入为Bean设置属性值。这是Spring IoC的核心能力——@Autowired@Resource等注解的处理都在这个阶段完成。

4.3 初始化阶段(Initialization)

这是生命周期中最复杂的阶段,包含多个子步骤。执行顺序必须严格遵循:

顺序步骤说明
BeanNameAware.setBeanName()传递Bean的ID/名称
BeanFactoryAware.setBeanFactory()传递BeanFactory实例
ApplicationContextAware.setApplicationContext()传递ApplicationContext实例
BeanPostProcessor.postProcessBeforeInitialization()初始化处理
@PostConstructJSR-250标准注解方式
InitializingBean.afterPropertiesSet()接口方式初始化
自定义init-methodXML或@Bean(initMethod="...")指定
BeanPostProcessor.postProcessAfterInitialization()初始化处理

💡关键点@PostConstructInitializingBean.afterPropertiesSet()→ 自定义init-method的执行顺序是固定的。AOP动态代理在BeanPostProcessor后置处理中创建——所以@Transactional@Async等注解在此时生效。

4.4 Aware接口详解

Aware接口是一组感知接口,让Bean能够感知到Spring容器的基础设施。

Aware接口回调方法作用
BeanNameAwaresetBeanName(String name)获取Bean在容器中的名称
BeanFactoryAwaresetBeanFactory(BeanFactory)获取BeanFactory实例
ApplicationContextAwaresetApplicationContext(ApplicationContext)获取ApplicationContext实例
BeanClassLoaderAwaresetBeanClassLoader(ClassLoader)获取类加载器
EnvironmentAwaresetEnvironment(Environment)获取环境配置
4.5 BeanPostProcessor详解

BeanPostProcessor是Spring中最强大的扩展点之一。它允许开发者在Bean初始化前后插入自定义逻辑。

@ComponentpublicclassMyBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName){// 初始化前执行——比如检查Bean是否满足某种条件System.out.println("Before initialization: "+beanName);returnbean;}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName){// 初始化后执行——AOP动态代理在此创建System.out.println("After initialization: "+beanName);returnbean;}}

💡BeanPostProcessor不是Bean生命周期的一部分,但它是在Bean生命周期中起重要作用的组件

4.6 销毁阶段(Destruction)

当容器关闭时,会按相反顺序触发销毁逻辑:

顺序步骤说明
@PreDestroyJSR-250标准注解方式
DisposableBean.destroy()接口方式销毁
自定义destroy-methodXML或@Bean(destroyMethod="...")指定

五、代码验证

下面通过一个完整的示例来验证Bean生命周期的执行顺序:

// ========== 1. 自定义Bean ==========@ComponentpublicclassLifecycleBeanimplementsBeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{publicLifecycleBean(){System.out.println("① 实例化:构造函数");}@AutowiredprivateSomeComponentsomeComponent;publicvoidsetSomeComponent(SomeComponentsomeComponent){System.out.println("② 属性填充:setSomeComponent");this.someComponent=someComponent;}@OverridepublicvoidsetBeanName(Stringname){System.out.println("③ Aware回调:BeanNameAware - "+name);}@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory){System.out.println("④ Aware回调:BeanFactoryAware");}@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext){System.out.println("⑤ Aware回调:ApplicationContextAware");}@PostConstructpublicvoidpostConstruct(){System.out.println("⑥ 初始化:@PostConstruct");}@OverridepublicvoidafterPropertiesSet(){System.out.println("⑦ 初始化:InitializingBean.afterPropertiesSet()");}@Bean(initMethod="customInit")publicclassMyConfig{// 自定义init-method}publicvoidcustomInit(){System.out.println("⑧ 初始化:自定义 init-method");}publicvoiddoWork(){System.out.println("⑨ 使用:业务方法被调用");}@PreDestroypublicvoidpreDestroy(){System.out.println("⑩ 销毁:@PreDestroy");}@Overridepublicvoiddestroy(){System.out.println("⑪ 销毁:DisposableBean.destroy()");}publicvoidcustomDestroy(){System.out.println("⑫ 销毁:自定义 destroy-method");}}// ========== 2. 自定义BeanPostProcessor ==========@ComponentpublicclassMyBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName){if(beaninstanceofLifecycleBean){System.out.println(" 🔹 BeanPostProcessor前置处理");}returnbean;}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName){if(beaninstanceofLifecycleBean){System.out.println(" 🔹 BeanPostProcessor后置处理(AOP代理在此创建)");}returnbean;}}// ========== 3. 启动容器 ==========@SpringBootApplicationpublicclassApplication{publicstaticvoidmain(String[]args){ConfigurableApplicationContextcontext=SpringApplication.run(Application.class,args);LifecycleBeanbean=context.getBean(LifecycleBean.class);bean.doWork();context.close();// 触发销毁}}

执行结果

① 实例化:构造函数 ② 属性填充:setSomeComponent ③ Aware回调:BeanNameAware - lifecycleBean ④ Aware回调:BeanFactoryAware ⑤ Aware回调:ApplicationContextAware 🔹 BeanPostProcessor前置处理 ⑥ 初始化:@PostConstruct ⑦ 初始化:InitializingBean.afterPropertiesSet() ⑧ 初始化:自定义 init-method 🔹 BeanPostProcessor后置处理(AOP代理在此创建) ⑨ 使用:业务方法被调用 ⑩ 销毁:@PreDestroy ⑪ 销毁:DisposableBean.destroy() ⑫ 销毁:自定义 destroy-method

六、避坑要点

错误/误区后果正确做法
混淆@PostConstructafterPropertiesSet()的执行顺序依赖初始化顺序错误@PostConstruct先执行,afterPropertiesSet()后执行
在构造函数中调用未注入的属性空指针异常属性注入完成后才能在@PostConstruct中使用
认为AOP在Bean实例化时就生效@Transactional不生效AOP代理在BeanPostProcessor后置处理中创建
BeanPostProcessor中创建新Bean破坏生命周期,可能导致循环依赖BeanPostProcessor只做增强处理,不创建新Bean
忘记调用context.close()销毁方法不执行在Spring Boot中无需手动处理,容器会自动关闭

七、面试高频考点

Q1:Spring Bean的生命周期有哪些阶段?

四个主要阶段:①实例化——容器通过反射调用构造函数创建实例;②属性填充——通过依赖注入设置属性值;③初始化——Aware回调 → BeanPostProcessor前置 →@PostConstructInitializingBean.afterPropertiesSet()→ 自定义init-method→ BeanPostProcessor后置;④销毁——@PreDestroyDisposableBean.destroy()→ 自定义destroy-method

Q2:@PostConstructInitializingBeaninit-method的执行顺序?

顺序是:@PostConstructInitializingBean.afterPropertiesSet()→ 自定义init-method@PostConstruct是JSR-250标准注解,优先级最高;InitializingBean是Spring接口方式;自定义init-method是XML或注解配置方式。

Q3:AOP代理是在生命周期的哪个阶段创建的?

AOP动态代理在BeanPostProcessor.postProcessAfterInitialization()中创建。也就是说,在Bean完成初始化之后,Spring会检查这个Bean是否需要被代理(比如是否有@Transactional@Async等注解),如果需要,就创建一个代理对象返回。

Q4:BeanPostProcessorBeanFactoryPostProcessor的区别?

BeanFactoryPostProcessor容器级别的扩展点,在所有Bean实例化之前执行,可以修改BeanDefinition(元数据)。BeanPostProcessorBean级别的扩展点,在Bean初始化前后执行,可以修改Bean实例本身。两者执行时机完全不同。

Q5:Aware接口的作用是什么?

Aware接口让Bean能够感知Spring容器的基础设施。比如BeanNameAware让Bean知道自己的名字,ApplicationContextAware让Bean能拿到ApplicationContext实例。这样Bean就可以在初始化时主动获取容器中的资源。


面试官追问陷阱(加分题)

追问1:“BeanPostProcessor本身是一个Bean吗?它自己会走生命周期吗?”

👉BeanPostProcessor本身也是由Spring容器管理的Bean,它自己也会经历完整的生命周期——实例化、属性填充、初始化。但有一个关键点:BeanPostProcessor的实例化会提前,在普通Bean实例化之前就完成,这样才能在普通Bean初始化时进行拦截处理。

追问2:“如果我在BeanPostProcessor.postProcessAfterInitialization()中返回了一个不同的对象(比如代理对象),会发生什么?”

👉 返回的对象会替换容器中原来的Bean实例。后续所有对这个Bean的依赖注入和getBean()调用,拿到的都是这个新对象。这正是AOP的实现原理——Spring在postProcessAfterInitialization()中检查Bean是否需要切面增强,如果需要,就返回一个CGLIB或JDK动态代理对象,替换掉原始Bean。

追问3:“Bean的销毁方法在什么情况下不会被调用?”

👉 ①容器非正常关闭(如kill -9强制杀死进程);②原型(prototype)作用域的Bean,容器不负责销毁;③单例Bean如果从未被使用(懒加载且没人调用),也不会触发销毁。


八、练习题

  1. 简答题:请按顺序说出Bean初始化的8个子步骤(从Aware回调到BeanPostProcessor后置处理)。

  2. 代码题:编写一个自定义BeanPostProcessor,在Bean初始化前后打印日志,并验证执行顺序。

  3. 分析题:某项目中@Transactional注解不生效,经过排查发现AOP代理没有创建。请分析可能的原因,并给出解决方案。

📊 你的学习进度

  • 当前:第74篇 / 共108篇 ·进阶篇:Spring全家桶(第73~82篇)
  • ✅ 已完成:基础篇44篇 + 第45~74篇
  • 📖 正在学:第74篇
  • ⏳ 待学习:第75~108篇

👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇

👉 下一篇文章预告

🚀下一篇:《第75篇:Spring AOP原理》

内容简介:AOP核心概念(切面、通知、切入点)、JDK动态代理 vs CGLIB、@Transactional底层原理、切面执行顺序、AOP失效场景。

👉Spring全家桶专题持续推进,拿下AOP!

📌《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询