Skip to content

说下 Spring Bean 的生命周期? ​

  • 标签:后端、Spring

🏛 业务架构师 ​

Bean 生命周期主线:实例化(构造器)→ 属性填充(依赖注入)→ Aware 回调(BeanName/BeanFactory/ApplicationContext)→ BeanPostProcessor 前置处理 → 初始化(@PostConstruct / InitializingBean / init-method)→ BeanPostProcessor 后置处理(AOP 代理在这里生成)→ 就绪使用 → 容器关闭时销毁(@PreDestroy)。

业务视角,这个流程的价值是"在哪里挂载业务动作":

  • @PostConstruct 做预热:启动时预加载缓存、预建连接、校验强配置——fail-fast 设计:关键配置缺失直接启动失败,好过带病上岗后在流量高峰爆炸。我要求核心服务都在此校验依赖(DB 连通、MQ 可用、关键配置完整);
  • InitializingBean/SmartInitializingSingleton 做装配后动作:所有单例就绪后的批量初始化(启动完成才构建本地缓存索引);
  • 销毁回调做优雅停机:关闭线程池、flush 缓冲、释放分布式锁——配合 K8s 的 preStop 与 SIGTERM,无损发布(不丢在途请求);
  • BeanPostProcessor 是框架与公司的扩展协议:自定义注解(如 @RateLimit、@Idempotent)的扫描处理都挂这里——公司级规范组件的标准接入点。

理解生命周期的排障价值:循环依赖为什么会得到"半成品"(实例化后提前暴露)、AOP 自调用为什么失效(代理是后置生成的)——一半的"Spring 玄学问题"都能在生命周期的时序图上找到答案。

一句话:生命周期是 Spring 的"业务初始化协议"——知道每个钩子的语义,预热、校验、优雅停机这些生产级动作才有正确的落点。

🏗 系统架构师 ​

Bean 生命周期我按"实例化 → 属性注入 → 初始化 → 使用 → 销毁"五阶段,标出关键扩展点:

  1. 实例化:容器根据 BeanDefinition 反射创建对象(构造器);
  2. 属性填充:依赖注入(@Autowired/setter);
    • 此前后有 Aware 回调:BeanNameAware、BeanFactoryAware、ApplicationContextAware(拿容器引用);
  3. 初始化前:BeanPostProcessor.postProcessBeforeInitialization(@PostConstruct 在这之后由 CommonAnnotationBeanPostProcessor 触发);
  4. 初始化:InitializingBean.afterPropertiesSet() → init-method / @Bean(initMethod);
  5. 初始化后:BeanPostProcessor.postProcessAfterInitialization——AOP 代理就在这里生成并返回代理对象(代理替换原对象放入容器);
  6. 使用:单例放一级缓存供注入;
  7. 销毁:容器 close 时 @PreDestroy → DisposableBean.destroy() → destroy-method。

两大扩展支柱要突出:BeanFactoryPostProcessor(改 BeanDefinition,配置类解析、自动配置的时机)与 BeanPostProcessor(改 Bean 实例,注入注解处理、AOP)——Spring 的"魔法"全部挂在这两个钩子上。

实战价值:排查 @Autowired 为 null / AOP 失效(生命周期时机不对)、循环依赖的提前暴露点、Aware 拿容器、init 里依赖未就绪等问题,都需要这张时序图做心智模型。

💻 全栈开发专家 ​

一句话主线:实例化 → 属性填充 → 初始化 → 使用 → 销毁,AOP 代理在初始化后生成。

1. 实例化:构造器/工厂方法创建原始对象。

2. 属性填充(依赖注入):populateBean,@Autowired/@Value 在这步注入(AutowiredAnnotationBeanPostProcessor)。

3. 初始化(有严格顺序):

text
① Aware 回调(BeanNameAware/BeanFactoryAware/ApplicationContextAware)
② BeanPostProcessor#postProcessBeforeInitialization
③ @PostConstruct → InitializingBean#afterPropertiesSet → init-method
④ BeanPostProcessor#postProcessAfterInitialization
   ← AOP 代理通常在这步生成(AbstractAutoProxyCreator)

4. 使用 → 容器关闭时:@PreDestroy → DisposableBean#destroy → destroy-method。

工程上真正有用的三个点(我踩过的坑):

  1. @PostConstruct 里依赖未注入的错觉:不会发生——属性填充在初始化之前;但构造器里拿 @Autowired 字段是 null(还没填充),很多人栽在这;
  2. BeanPostProcessor 是扩展金矿:我写过统一的"方法耗时监控"后置处理器(代理包装),还有 @ConfigurationProperties 绑定校验(绑定完在 afterPropertiesSet 里 validate);
  3. Aware 拿容器对象:需要 ApplicationContext 时实现 ApplicationContextAware 注入,但更好的做法是构造器注入,Aware 方式让 Bean 耦合 Spring API。

加分:结合三级缓存讲"循环依赖时早期暴露发生在实例化后、属性填充前",两道题就串起来了。