说下 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 生命周期我按"实例化 → 属性注入 → 初始化 → 使用 → 销毁"五阶段,标出关键扩展点:
- 实例化:容器根据 BeanDefinition 反射创建对象(构造器);
- 属性填充:依赖注入(@Autowired/setter);
- 此前后有 Aware 回调:BeanNameAware、BeanFactoryAware、ApplicationContextAware(拿容器引用);
- 初始化前:BeanPostProcessor.postProcessBeforeInitialization(@PostConstruct 在这之后由 CommonAnnotationBeanPostProcessor 触发);
- 初始化:InitializingBean.afterPropertiesSet() → init-method / @Bean(initMethod);
- 初始化后:BeanPostProcessor.postProcessAfterInitialization——AOP 代理就在这里生成并返回代理对象(代理替换原对象放入容器);
- 使用:单例放一级缓存供注入;
- 销毁:容器 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。
工程上真正有用的三个点(我踩过的坑):
- @PostConstruct 里依赖未注入的错觉:不会发生——属性填充在初始化之前;但构造器里拿 @Autowired 字段是 null(还没填充),很多人栽在这;
- BeanPostProcessor 是扩展金矿:我写过统一的"方法耗时监控"后置处理器(代理包装),还有 @ConfigurationProperties 绑定校验(绑定完在 afterPropertiesSet 里 validate);
- Aware 拿容器对象:需要 ApplicationContext 时实现 ApplicationContextAware 注入,但更好的做法是构造器注入,Aware 方式让 Bean 耦合 Spring API。
加分:结合三级缓存讲"循环依赖时早期暴露发生在实例化后、属性填充前",两道题就串起来了。