侧边栏壁纸
博主头像
牧云

怀璧慎显,博识谨言。

  • 累计撰写 198 篇文章
  • 累计创建 19 个标签
  • 累计收到 8 条评论

目 录CONTENT

文章目录

Spring Bean 生命周期

秋之牧云
2026-05-14 / 0 评论 / 0 点赞 / 7 阅读 / 0 字

1. 生命周期全景图 (Mermaid)

以下流程图展示了 Spring Bean 从实例化到销毁的完整路径,以及关键扩展点的介入时机。

[开始]
  |
  v
1. 实例化 (Instantiation)
  |  <--- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
  v
2. 属性填充 (Population)
  |  <--- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
  |  <--- InstantiationAwareBeanPostProcessor.postProcessProperties (@Autowired)
  v
3. Aware 接口回调
  |  (如果实现 BeanNameAware, ApplicationContextAware 等)
  v
4. BeanPostProcessor.postProcessBeforeInitialization
  |
  v
5. 初始化 (Initialization)
  |  ---> @PostConstruct
  |  ---> InitializingBean.afterPropertiesSet()
  |  ---> 自定义 init-method
  v
6. BeanPostProcessor.postProcessAfterInitialization
  |  *** AOP 代理对象通常在此阶段生成 ***
  v
7. Bean 就绪 (Ready)
  |  (Bean 放入单例池,可供其他 Bean 依赖注入)
  |
  v
[容器关闭时触发销毁]
  |
  v
8. 销毁 (Destruction)
  |  ---> @PreDestroy
  |  ---> DisposableBean.destroy()
  |  ---> 自定义 destroy-method
  v
[结束]

2. 核心阶段与扩展点映射

阶段关键动作核心扩展点/接口典型应用场景
实例化创建对象实例InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation返回代理对象以短路后续流程;AspectJ 集成
属性填充依赖注入 (DI)InstantiationAwareBeanPostProcessor.postProcessProperties@Autowired, @Value 注解的处理逻辑
Aware 回调注入容器资源BeanNameAware, ApplicationContextAware获取 Bean 名称、上下文环境、事件发布器等
初始化前预处理BeanPostProcessor.postProcessBeforeInitialization检查注解、修改属性、动态代理准备
初始化执行业务初始化@PostConstruct InitializingBean init-method数据库连接池初始化、缓存预热、参数校验
初始化后后处理/AOPBeanPostProcessor.postProcessAfterInitializationAOP 代理对象创建、最终包装
销毁资源清理@PreDestroy DisposableBean destroy-method关闭连接、释放线程池、保存状态

3. 容器级扩展点(在 Bean 实例化之前)

这些扩展点作用于容器层面,而非单个 Bean:

  • ApplicationContextInitializer: 容器刷新前调用。
    • 场景: 激活 Profile、设置 Context ID。
  • BeanDefinitionRegistryPostProcessor: BeanDefinition 加载后执行。
    • 场景: 动态注册 Bean(如 MyBatis Mapper 扫描、Feign Client 生成)。
  • BeanFactoryPostProcessor: Bean 实例化前修改元数据。
    • 场景: 解析占位符 ${...}、加密属性解密。

4. 关键注意事项与陷阱

A. 循环依赖与三级缓存

  • 机制: Spring 通过三级缓存解决单例、 setter/field 注入的循环依赖。
  • 流程: 实例化后 -> 将 ObjectFactory 放入三级缓存 -> 其他 Bean 获取早期引用 -> 完成属性填充。
  • 局限: 构造器注入Prototype 作用域的循环依赖无法自动解决,需使用 @Lazy 或重构代码。

B. 初始化方法执行顺序

严格遵循以下顺序,建议统一使用一种方式以避免混乱:

  1. @PostConstruct (JSR-250 标准,推荐)
  2. InitializingBean.afterPropertiesSet() (Spring 接口,强耦合)
  3. 自定义 init-method (配置指定)

C. AOP 代理的时机

  • 关键点: AOP 代理通常在 postProcessAfterInitialization 中生成。
  • 陷阱: 在 @PostConstructafterPropertiesSet 中调用当前 Bean 的方法,不会经过 AOP 切面(因为此时代理尚未完全接管或内部调用 bypass 代理)。事务注解在这些阶段无效。

D. 作用域差异

  • Singleton: 容器管理完整生命周期(创建+销毁)。
  • Prototype: 容器只负责创建和属性填充,不负责销毁。开发者需自行管理资源释放。
  • Request/Session: 生命周期绑定 Web 请求或会话。

E. 性能优化

  • BeanPostProcessor 会对容器中所有 Bean 执行。务必保持其逻辑轻量,避免在 postProcessBefore/AfterInitialization 中进行耗时操作(如远程调用、复杂计算),否则会显著增加应用启动时间。

5. 总结

Spring Bean 生命周期是一个高度可扩展的过程。理解扩展点的介入时机(特别是 BPP 的前后处理)、循环依赖的解决机制以及AOP 代理生成的滞后性,是掌握 Spring 核心原理的关键。在实际开发中,应优先使用注解(@PostConstruct/@PreDestroy)进行生命周期管理,并利用容器级扩展点处理框架集成需求。

0

评论区