Spring Bean 生命周期:从实例化到销毁,一篇讲透
面试官:“说一下 Spring Bean 的生命周期。”
你:“Bean 的生命周期包括:实例化、填充属性、初始化前(BeanPostProcessor)、初始化(afterPropertiesSet/init-method)、初始化后、正常使用、销毁。”
面试官:“那 Aware 接口是在哪个阶段调用的?BeanPostProcessor 和 InitializingBean 的执行顺序是怎样的?”
你:“……”
很多人能背出主要阶段,但一追问细节就乱了。本文从源码角度,把 Bean 从创建到销毁的完整流程讲清楚,并附上代码示例和常见面试追问。
一、Bean 生命周期总览
Spring 容器管理 Bean 的完整生命周期可以分为三大阶段:创建(实例化 → 属性填充 → 初始化)→ 使用 → 销毁。其中初始化前后还穿插着各种 Aware 接口和 BeanPostProcessor 扩展点。
完整流程(按时间顺序):
1. 实例化(构造器/工厂方法) 2. 属性赋值(依赖注入) 3. BeanNameAware.setBeanName() 4. BeanClassLoaderAware.setBeanClassLoader() 5. BeanFactoryAware.setBeanFactory() 6. ApplicationContextAware.setApplicationContext()(若容器是 ApplicationContext) 7. BeanPostProcessor.postProcessBeforeInitialization() 8. InitializingBean.afterPropertiesSet() 9. 自定义 init-method 10. BeanPostProcessor.postProcessAfterInitialization() 11. 使用 Bean 12. DisposableBean.destroy() 13. 自定义 destroy-method下图直观展示了各阶段顺序:
实例化 → 属性填充 → Aware接口 → 前置处理 → 初始化 → 后置处理 → 使用 → 销毁二、各阶段详解
1. 实例化(Instantiation)
容器通过构造器或工厂方法创建 Bean 的实例。此时 Bean 对象已经存在,但属性尚未赋值(均为默认值或 null)。
- 默认使用无参构造器,如果类没有无参构造器且未指定构造参数,Spring 会抛出异常。
- 可以通过
@Autowired标注有参构造器,或使用factory-method。
2. 填充属性(Populate Properties)
Spring 根据配置(XML 中的<property>、注解@Value、@Autowired等)为 Bean 的属性赋值。依赖注入发生在这个阶段。
- 如果存在循环依赖,Spring 会提前暴露半成品对象(通过三级缓存解决)。
- 属性赋值完成后,Bean 的状态基本完整(但可能尚未完成全部初始化)。
3. Aware 接口回调
如果 Bean 实现了某个 Aware 接口,Spring 会注入对应的资源。执行顺序固定:
| Aware 接口 | 注入的资源 |
|---|---|
BeanNameAware | Bean 在容器中的名称(id/name) |
BeanClassLoaderAware | 加载 Bean 的 ClassLoader |
BeanFactoryAware | 当前的BeanFactory实例 |
ApplicationContextAware | 当前的ApplicationContext实例(仅在 ApplicationContext 容器中生效) |
注意:
ApplicationContextAware在BeanFactoryAware之后调用,且要求容器是ApplicationContext类型(若为BeanFactory则不会调用)。
4. BeanPostProcessor 前置处理
BeanPostProcessor接口提供了两个方法:postProcessBeforeInitialization和postProcessAfterInitialization。在初始化方法执行前,Spring 会调用所有注册的BeanPostProcessor的postProcessBeforeInitialization方法。
典型用途:修改 Bean 的属性、生成代理对象、执行自定义检查等。Spring 内部很多功能(如@Autowired解析、AOP 代理创建)都是通过BeanPostProcessor实现的。
5. 初始化(Initialization)
初始化阶段包括两部分:
InitializingBean.afterPropertiesSet():如果 Bean 实现了该接口,Spring 会调用此方法。- 自定义 init-method:可以通过
@Bean(initMethod = "init")或 XML 中的init-method指定一个无参方法,在 afterPropertiesSet 之后执行。
执行顺序:afterPropertiesSet()先执行,然后执行自定义 init-method。
6. BeanPostProcessor 后置处理
初始化完成后,Spring 调用所有BeanPostProcessor的postProcessAfterInitialization方法。此时 Bean 已经完全准备好,可以返回给调用方。
AOP 代理的创建通常发生在这个阶段:AbstractAutoProxyCreator是BeanPostProcessor的实现,在postProcessAfterInitialization中判断是否需要为 Bean 生成代理对象。
7. Bean 使用
Bean 已经存在于容器中,可以供其他组件@Autowired或通过getBean()获取,执行业务逻辑。
8. 销毁(Destruction)
当容器关闭时(如ApplicationContext.close()),会销毁所有单例 Bean。销毁阶段包括:
DisposableBean.destroy():如果 Bean 实现了该接口,Spring 会调用此方法。- 自定义 destroy-method:通过
@Bean(destroyMethod = "cleanup")或 XML 中的destroy-method指定,在 DisposableBean 的 destroy 之后执行。
作用域影响:上述生命周期描述适用于单例作用域(singleton)。对于原型作用域(prototype),Spring 只负责创建和初始化,不管理销毁,需要用户自行处理。
三、代码示例:完整演示生命周期
@ComponentpublicclassLifecycleBeanimplementsBeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{privateStringname;publicLifecycleBean(){System.out.println("1. 实例化:构造器");}@AutowiredpublicvoidsetName(@Value("testBean")Stringname){this.name=name;System.out.println("2. 属性填充:setName("+name+")");}@OverridepublicvoidsetBeanName(Stringname){System.out.println("3. BeanNameAware: "+name);}@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{System.out.println("4. BeanFactoryAware");}@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{System.out.println("5. ApplicationContextAware");}@OverridepublicvoidafterPropertiesSet()throwsException{System.out.println("7. InitializingBean.afterPropertiesSet()");}@PostConstruct// JSR-250,等价于 init-method 但更常用publicvoidpostConstruct(){System.out.println("6. @PostConstruct (在 afterPropertiesSet 之前?注意顺序)");// 实际执行顺序:@PostConstruct 在 afterPropertiesSet 之前,但早于自定义 init-method// 为清晰,这里单独标注顺序,实际需看注解处理器优先级。}@Bean(initMethod="customInit")// 配置类中指定publicvoidcustomInit(){System.out.println("8. 自定义 init-method");}@Overridepublicvoiddestroy()throwsException{System.out.println("9. DisposableBean.destroy()");}@PreDestroypublicvoidpreDestroy(){System.out.println("10. @PreDestroy (在 destroy 之前)");}publicvoidcustomDestroy(){System.out.println("11. 自定义 destroy-method");}}注意:
@PostConstruct和@PreDestroy是 JSR-250 标准,Spring 支持,执行时机分别在afterPropertiesSet之前和destroy之前。
四、BeanPostProcessor 的使用示例
@ComponentpublicclassCustomBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{if(beaninstanceofLifecycleBean){System.out.println("BeanPostProcessor.before: "+beanName);}returnbean;}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{if(beaninstanceofLifecycleBean){System.out.println("BeanPostProcessor.after: "+beanName);}returnbean;}}执行顺序输出(简化):
1. 实例化 2. 属性填充 3. BeanNameAware 4. BeanFactoryAware 5. ApplicationContextAware BeanPostProcessor.before 6. @PostConstruct 7. afterPropertiesSet 8. 自定义 init-method BeanPostProcessor.after ... 使用 ... BeanPostProcessor.before // 原型Bean每次创建都会经过五、常见面试追问
Q1:BeanPostProcessor和InitializingBean的区别?
InitializingBean是Bean 自身的初始化回调,只针对当前 Bean。BeanPostProcessor是容器级的扩展点,对所有 Bean 生效,可以在初始化前后进行统一增强(如代理、属性修改)。
Q2:AOP 代理在哪个阶段创建?
在BeanPostProcessor.postProcessAfterInitialization阶段,具体是AbstractAutoProxyCreator类的实现。因此,如果 Bean 需要被代理,最终返回的是代理对象而非原始对象。
Q3:@PostConstruct和@PreDestroy与afterPropertiesSet、destroy的先后顺序?
@PostConstruct在afterPropertiesSet之前执行(因为CommonAnnotationBeanPostProcessor处理 JSR-250 注解的优先级高于InitializingBean)。@PreDestroy在destroy之前执行。
Q4:原型 Bean 的生命周期有什么不同?
- 原型 Bean 在每次请求时都会创建新实例,执行实例化 → 属性填充 → 初始化(包括 Aware、PostConstruct、InitializingBean 等),但不会执行销毁阶段(容器不管理原型 Bean 的销毁)。用户需要自行处理资源释放。
Q5:FactoryBean和BeanFactory有什么区别?
BeanFactory是 Spring 容器的顶级接口,负责管理 Bean。FactoryBean是一个特殊的 Bean,用于生成复杂对象。当通过&前缀获取时返回 FactoryBean 本身,否则返回其getObject()创建的对象。FactoryBean 的生命周期与普通 Bean 类似,但它的getObject()中创建的对象不由 Spring 管理生命周期(除非声明为 prototype)。
六、生命周期扩展点总结
| 扩展点 | 时机 | 用途 |
|---|---|---|
BeanPostProcessor | 初始化前后 | 全局增强,如代理、属性注入 |
InstantiationAwareBeanPostProcessor | 实例化前后、属性填充前后 | 控制实例化、属性赋值 |
BeanFactoryAware | 属性填充后,初始化前 | 获取容器引用 |
InitializingBean | 自定义初始化前 | 执行特定初始化逻辑 |
DisposableBean | 销毁时 | 执行资源清理 |
@PostConstruct/@PreDestroy | 同 InitializingBean / DisposableBean | 注解方式更简洁 |
ApplicationListener | 容器事件发布时 | 监听容器启动、关闭等事件 |
七、总结
| 阶段 | 关键动作 |
|---|---|
| 实例化 | 调用构造器 / 工厂方法 |
| 属性填充 | 依赖注入 |
| Aware 回调 | 注入 BeanName、BeanFactory、ApplicationContext |
| 前置处理 | BeanPostProcessor.postProcessBeforeInitialization |
| 初始化 | @PostConstruct → afterPropertiesSet → init-method |
| 后置处理 | BeanPostProcessor.postProcessAfterInitialization |
| 使用 | 业务调用 |
| 销毁 | @PreDestroy → destroy → destroy-method |
一句话记住生命周期:构造填充属 Aware,前置初始化后置跑;用完销毁两步走,PreDestroy 和 destroy。
理解 Bean 生命周期不仅能让你在面试中对答如流,还能帮助你写出更优雅的扩展组件(如自定义BeanPostProcessor)。希望这篇文章能帮你彻底掌握 Spring Bean 的生命周期,欢迎继续讨论。