当前位置: 首页 > news >正文

Spring Bean 生命周期:搞懂这 8 步,面试再也不怕被问

目录

一、完整流程图

二、每个阶段实际在干嘛

① 实例化 — Spring 通过反射 new 对象

② 属性注入 — @Autowired/@Value 填值

③ Aware 回调 — Spring 告诉你"你是谁"

④ BeanPostProcessor.Before — 初始化前拦截

⑤ 初始化 — 真正的干活阶段(三步走)

⑥ BeanPostProcessor.After — AOP 代理就在这里!

⑧ 销毁 — 容器关闭时的善后(三步走)

三、默认执行 vs 需要主动配置

🟢 默认执行的(你不写任何代码也会走)

🔵 需要你主动写代码才会触发的

四、初始化前后的 BeanPostProcessor 作用

五、一句话总结全流程

六、面试高频点

七、面试话术

八、验证代码



一、完整流程图


二、每个阶段实际在干嘛

① 实例化 — Spring 通过反射 new 对象

// Spring 做的事:new UserService() // 这时候所有属性都是 null 或默认值 UserService userService = new UserService(); ​ // 打印出来是: dbUrl = null ← @Value 还没注入! maxActive = 0 ← @Value 还没注入! configLoader = null ← @Autowired 还没注入!

实际意义:千万别在构造方法里调用这些属性,会报空指针。


② 属性注入 — @Autowired/@Value 填值

@Autowired private ConfigLoader configLoader; // 这时候才注入 @Value("${db.url}") private String dbUrl; // 这时候才注入 ​ // 到 @PostConstruct 时,值已经正常了: dbUrl = jdbc:mysql://localhost:3306/userdb ← 不再是 null configLoader = ConfigLoader{version='v2.3.1'...} ← 不再是 null

实际意义:你的@Autowired@Value都在这里生效。


③ Aware 回调 — Spring 告诉你"你是谁"

setBeanName → "我叫 userService" setBeanFactory → "我已经能看到容器里有其他 Bean 了" setApplicationContext → "容器里一共 9 个 Bean"

实际意义:

  • BeanNameAware→ 项目中几乎不用

  • ApplicationContextAware→ 极少数项目用来手动获取 Bean


④ BeanPostProcessor.Before — 初始化前拦截

实际意义:Spring 自己用它来解析@Autowired@Value等注解。


⑤ 初始化 — 真正的干活阶段(三步走)

执行顺序方式代码你要怎么写
@PostConstruct方法上加注解方法上加@PostConstruct
InitializingBean实现接口重写afterPropertiesSet()implements InitializingBean
init-method@Bean里指定方法名@Bean(initMethod="xxx")

实际用途:

  • 启动资源(创建数据库连接池、启动定时任务)

  • 校验配置(检查必要属性是否都注入了)

  • 预热数据(从数据库加载热点数据到内存)


⑥ BeanPostProcessor.After — AOP 代理就在这里!

实际意义:如果你给 UserService 加了@Transactional,这步会返回一个CGLIB 代理对象,而不是原始对象。这就是为什么@Transactional只在通过 Spring 容器获取的 Bean 上生效。


⑧ 销毁 — 容器关闭时的善后(三步走)

执行顺序方式代码你要怎么写
@PreDestroy方法上加注解方法上加@PreDestroy
DisposableBean实现接口重写destroy()implements DisposableBean
destroy-method@Bean里指定方法名@Bean(destroyMethod="xxx")

实际用途:关闭线程池、断开数据库连接、保存未处理的消息。


三、默认执行 vs 需要主动配置

🟢 默认执行的(你不写任何代码也会走)

  • 实例化:只要声明了@Component/@Bean就会走

  • 属性注入:只要有@Autowired@Value就会注入

  • AOP 代理:Spring Boot 默认自带,加@Transactional就生效

🔵 需要你主动写代码才会触发的

扩展点你要怎么写平时用过吗
BeanNameAwareimplements BeanNameAware❌ 几乎不用
ApplicationContextAwareimplements ApplicationContextAware⚠️ 极少数项目用
BeanPostProcessorimplements BeanPostProcessor并注册❌ 没用过
@PostConstruct方法上加注解✅ 最常用
@PreDestroy方法上加注解⚠️ 偶尔
InitializingBeanimplements InitializingBean❌ 很少直接用
initMethod@Bean(initMethod="xxx")❌ 很少直接用

你日常开发里 99% 的 Bean 生命周期就是:

① 实例化 → ② 属性注入 → ③ 就绪 ↘ 如果加了 @PostConstruct,中间插一步 ↘ 如果加了 @Transactional,最后变成代理对象

四、初始化前后的 BeanPostProcessor 作用

阶段一句话作用
初始化属性注入完成后,Bean 还需要"做点什么准备"才能真正干活(启动连接池、校验配置、加载缓存)
初始化前拦截Spring 在初始化之前插入一个"卡点",让你可以预处理(Spring 自己用它解析@Autowired
初始化后拦截Bean 初始化完成后,拦截器可以替换整个对象(AOP 代理就是在这里把原始对象替换成代理对象的)

五、一句话总结全流程

new出来(空的) ↓ 填依赖(@Autowired生效) ↓ 告诉我你是谁(Aware) ↓ 初始化前(BeanPostProcessor ✋) ↓ @PostConstruct → 准备资源 afterPropertiesSet → 检查配置 init-method → 加载缓存 ↓ 初始化后(AOP代理就在这里!🤖) ↓ === 可以用了!调业务方法 === ↓ 容器关闭 → @PreDestroy → destroy → destroy-method → 释放资源

六、面试高频点

问题答案
AOP 代理什么时候创建的?BeanPostProcessor.postProcessAfterInitialization()
@Autowired 在哪工作的?属性注入阶段,由AutowiredAnnotationBeanPostProcessor处理
@PostConstruct vs InitializingBean 谁先?@PostConstruct
prototype 会被销毁吗?不会!Spring 只管理 singleton 的销毁
BeanPostProcessor 可以用几个?多个,按Ordered接口排序执行
Spring Boot 默认用什么代理?CGLIBspring.aop.proxy-target-class=true

七、面试话术

问:Bean 有哪几种初始化方式?执行顺序是什么?

有三种,按顺序执行:

  1. @PostConstruct(注解方式)—— 方法上加注解

  2. InitializingBean(接口方式)—— 实现接口重写afterPropertiesSet()

  3. init-method(配置方式)—— 在@Bean(initMethod="xxx")里指定

其中最常用的是@PostConstruct,因为它最简单——加个注解就行。 顺序是固定的,由 Spring 源码AbstractAutowireCapableBeanFactory.doCreateBean()决定。 实际开发中,90% 的场景只需要用@PostConstruct就够了。

问:BeanPostProcessor 的 Before 和 After 有什么区别?

  • Before(初始化前):Spring 自己用它来解析@Autowired@Value等注解

  • After(初始化后):这是 AOP 创建代理对象的地方。如果你加了@Transactional,Spring 在这步把原始 Bean 替换成 CGLIB 代理对象

一句话总结:Before 是给 Spring 自己用的,After 是给 AOP 用的。


八、验证代码

代码项目在本账号的仓库中:bean-init-demo可以直接运行

预期输出如下:

【构造方法】MyService 被 new 出来了(还没注入属性) 【属性注入】name 被设置了:温度监控服务 ​ 【方式一 · @PostConstruct】我执行了! ← 第一个执行 【方式二 · InitializingBean】我执行了! ← 第二个执行 【方式三 · init-method(配置)】我执行了! ← 第三个执行 ​ 【业务】MyService 在干活,name=温度监控服务 ​ 【销毁一 · @PreDestroy】我执行了! ← 第一个销毁 【销毁二 · DisposableBean】我执行了! ← 第二个销毁 【销毁三 · destroy-method】我执行了! ← 第三个销毁
http://www.jsqmd.com/news/1072219/

相关文章:

  • Linux 中断处理:从硬件信号到软中断的全链路剖析
  • 构建个人云游戏服务器:Sunshine开源串流平台终极指南
  • 从云端到本地,迁移大模型工作流的成本分析
  • PCIE Transaction Layer(事务)详解 一
  • 小程序商城哪个平台好
  • 长沙软件开发公司服务能力与交付质量实测大纲
  • WarcraftHelper魔兽争霸III终极优化工具:3步解锁现代游戏体验完整指南
  • 案例四:资讯聚合APP与数据看板演示系统开发项目
  • 制造业AI视觉质检实战:5万张产品图的数据本地化训练与存储
  • 大学AI通识课实操平台推荐:让文科生也能轻松学AI
  • Beyond Compare 5:3步快速激活与开源密钥生成工具终极指南
  • 基于AI宏观因子模型的黄金市场分析:通胀压力边际缓和下的黄金低位回升多因子定价框架
  • storage + Monitoring 2026-6-23
  • COM3D2.MaidFiddler:5分钟掌握《COM3D2》终极实时编辑器
  • 终极视频加速指南:如何用Video Speed Controller提升3倍学习效率
  • C++:switch
  • PostgreSQL 高可用集群故障分析实战:主节点宕机后未发生自动切换问题排查与解决
  • 躺床上刷手机总乱转?一键关掉自动旋转,再也不晃眼!
  • 智能考勤教务系统对比,降低机构运营人力成本
  • 2026年腾讯云 618 活动说明及 Hermes Agent/OpenClaw配置Token Plan新手快速入门
  • 深圳地区等保2.0超融合方案选型指南与行业实践案例
  • 2026年度蓝光光谱照度计产业技术发展报告:从实验室到产线的关键检测节点
  • 终极RE引擎模组框架REFramework:如何为生化危机、鬼泣等游戏构建完整的脚本平台
  • 日本发布比肩Fable5的模型?Fugu Ultra初探!
  • 如何零成本解锁Wand专业版功能?开源增强工具为你提供完美解决方案
  • 用JDBC + AOP 实现的数据库加密切面能不能切西瓜?
  • 建议收藏!Wireshark 流量分析超详细例题精讲,零基础从入门到精通实战教程
  • 分布式时序数据库TimeLyre :原生多模态、高性能计算、快速时序回放分析
  • Meta SilverTorch 解读:为什么推荐系统要把索引也做成模型
  • 云原生可观测性体系构建:Prometheus + Grafana 全栈监控方案设计与落地