• Spring Bean 的生命周期简单易懂。在一个 bean 实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样的,当一个 bean 不在被调用时需要进行相关的析构操作,并从 bean 容器中移除。

  • Spring bean factory 负责管理在 spring 容器中被创建的 bean 的生命周期。Bean 的生命周期由两组回调(call back)方法组成。

    • 初始化之后调用的回调方法。
    • 销毁之前调用的回调方法。
  • Spring 框架提供了以下四种方式来管理 bean 的生命周期事件:

    • InitializingBean 和 DisposableBean 回调接口
    • 针对特殊行为的其他 Aware 接口
    • Bean 配置文件中的 Custom init() 方法和 destroy() 方法
    • @PostConstruct 和 @PreDestroy 注解方式

四种回调方式列齐了,但生命周期真正的考点是完整顺序:从实例化到销毁的十几步中,Aware、后处理器、初始化回调各自的插入点。本文给出一条可背可推的主线顺序,并讲清每类扩展点的用途与优先级。

主线顺序(单例 bean)

  1. 实例化:createBeanInstance——构造器/工厂方法创建裸对象(依赖注入之前)
  2. 属性填充:populateBean——@Autowired/@Value/refs 注入;循环依赖在此靠三级缓存解决
  3. Aware 回调:BeanNameAware → BeanClassLoaderAware → BeanFactoryAware →(后处理器补充的 EnvironmentAware/ApplicationContextAware 等)
  4. 初始化前:BeanPostProcessor.postProcessBeforeInitialization——@PostConstruct 在此被 CommonAnnotationBeanPostProcessor 执行
  5. 初始化:InitializingBean.afterPropertiesSet → 自定义 init-method(@Bean(initMethod=…) / xml init-method)
  6. 初始化后:BeanPostProcessor.postProcessAfterInitialization——AOP 代理在此生成(AbstractAutoProxyCreator)
  7. 就绪使用:放入单例池 singletonObjects
  8. 销毁:容器 close 时 @PreDestroy → DisposableBean.destroy → destroy-method

记忆锚点:注入在 Aware 前,@PostConstruct 在 afterPropertiesSet 前,代理在最后一步——三个”前/后”关系覆盖了绝大多数追问。

四类扩展点的定位与优先级

扩展点 触发点 典型用途 侵入性
@PostConstruct/@PreDestroy 初始化前后 资源预热/释放(JSR250 标准) 低(注解)
InitializingBean/DisposableBean 同上(注解之后) 框架内部组件常用 中(耦合 Spring 接口)
init-method/destroy-method 同上(接口之后) XML/配置类指定已有方法 低
Aware 族 属性填充后 获取容器设施(name/context/env) 中
BeanPostProcessor 初始化前后全局 AOP、代理、字段加工(容器级扩展) 容器级

同一 bean 同时定义多种初始化回调时执行顺序:@PostConstruct → afterPropertiesSet → init-method(销毁逆序同构)。业务代码优先 @PostConstruct(标准注解、不耦合接口);框架/中间件才用接口级回调。

生命周期与 scope 的交互

  • singleton:随容器启动创建(预实例化)、随容器关闭销毁,全周期一次
  • prototype:每次 getBean 走 1-6 步,但容器不管理销毁——@PreDestroy 对 prototype 不触发,资源释放需调用方负责(这是 prototype 最大的坑)
  • request/session:Web 作用域,随 Web 生命周期创建销毁,配合 scoped-proxy 注入单例

常见坑清单

  • 在构造器里做重初始化:依赖还没注入(populate 在后),NPE 高发;重活放 @PostConstruct
  • @PostConstruct 里调用本类被代理的方法期望事务生效:代理在第 6 步才生成,此时还是裸对象,自调用无增强
  • 依赖”其他 bean 已就绪”:单例初始化顺序由依赖图决定,跨 bean 的启动后逻辑应监听 ContextRefreshedEvent 而非各自 @PostConstruct 猜顺序
  • 销毁不执行:非正常关闭(kill -9)或 prototype——资源泄漏来源

一句话主线

Bean 生命周期 = 实例化 → 注入 → Aware → 初始化前(@PostConstruct)→ 初始化(接口/方法)→ 初始化后(AOP 代理)→ 使用 → 销毁(三档逆序);扩展点按”注解优先、接口次之、配置兜底”选用,scope 决定容器管不管销毁。顺序记住三个锚点,其余步骤皆可定位。