Spring Bean生命周期线性执行顺序详解
(基于Spring 6.x版本,时间戳:2025年3月3日 01:17)
一、完整生命周期流程图
实例化 → 属性注入 → Aware回调 → BeanPostProcessor前置 → 初始化 → BeanPostProcessor后置 → 运行期 → 销毁
二、分阶段线性执行顺序
- 实例化阶段
- 触发条件:容器启动或首次请求Bean时
- 关键动作:
▸ 通过构造器/工厂方法创建对象实例
▸ 若实现InstantiationAwareBeanPostProcessor接口,优先执行postProcessBeforeInstantiation()(可跳过默认实例化)
- 属性注入阶段
- 核心操作:
▸ 按类型/名称注入依赖(处理@Autowired、@Resource)
▸ 解析占位符和SpEL表达式(@Value)
- 扩展点:
▸ InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() (干预属性注入逻辑)
▸ InstantiationAwareBeanPostProcessor.postProcessProperties() (自定义属性处理)
- Aware接口回调
- 执行顺序:
▸ BeanNameAware.setBeanName()
▸ BeanClassLoaderAware.setBeanClassLoader()
▸ BeanFactoryAware.setBeanFactory()
▸ 其他扩展Aware接口(如EnvironmentAware, ApplicationContextAware)
- BeanPostProcessor前置处理
- 核心逻辑:
▸ 遍历所有BeanPostProcessor执行postProcessBeforeInitialization()
▸ 处理@PostConstruct注解方法(通过CommonAnnotationBeanPostProcessor实现)
- 初始化阶段
- 执行顺序:
▸ InitializingBean.afterPropertiesSet()
▸ XML/注解声明的init-method(如@Bean(initMethod="customInit"))
- BeanPostProcessor后置处理
- 关键作用:
▸ 执行postProcessAfterInitialization()
▸ 生成代理对象(如AOP在此阶段完成)
- 运行期阶段
- 状态特征:
▸ Bean进入就绪状态,可被其他组件依赖
▸ 单例Bean驻留在IoC容器中,原型Bean每次请求新建实例
- 销毁阶段
- 逆序执行逻辑:
▸ @PreDestroy注解方法
▸ DisposableBean.destroy()
▸ 自定义destroy-method
- 触发条件:
▸ 容器关闭(ConfigurableApplicationContext.close() )
▸ 仅针对单例Bean执行
三、特殊场景执行差异
场景 | 差异点 |
Prototype作用域Bean | 不执行销毁阶段(步骤8),容器不跟踪其生命周期 |
延迟初始化Bean | 步骤1-6在首次请求时触发,而非容器启动时 |
循环依赖 | 通过三级缓存提前暴露半成品Bean,但初始化流程仍按完整顺序执行 |
四、调试与验证方法
- 日志观察:
public class DebugBean implements InitializingBean, DisposableBean {
@PostConstruct
public void post() { System.out.println("@PostConstruct 执行"); }
@PreDestroy
public void pre() { System.out.println("@PreDestroy 执行"); }
@Override
public void afterPropertiesSet() { System.out.println("InitializingBean 回调"); }
@Override
public void destroy() { System.out.println("DisposableBean 回调"); }
}
- 断点追踪:
▸ 在AbstractAutowireCapableBeanFactory的initializeBean()方法设置断点
▸ 监控BeanPostProcessor实现类的执行堆栈
五、设计启示
- 扩展点选择策略:
- 优先使用@PostConstruct/@PreDestroy(JSR-250标准)
- 避免同时实现InitializingBean和定义init-method(导致执行顺序混淆)
- 性能优化:
- 减少BeanPostProcessor数量(影响所有Bean的初始化速度)
- 对非必要Aware接口实现保持谨慎(增加耦合度)
总结:Spring Bean生命周期是一个严格线性但高度可扩展的流程,理解其执行顺序对解决依赖注入异常、优化启动性能、实现高级扩展功能(如自定义作用域)具有关键意义。