Spring Bean 的生命周期是指从 Bean 的定义加载 开始,经历 实例化、属性赋值、初始化,直到 容器销毁 的完整过程。理解生命周期的核心在于掌握 IOC(控制反转) 和 DI(依赖注入) 的执行顺序,以及如何在各个阶段进行干预。
以下是 Spring Bean 生命周期的详细拆解,分为 4 个主要阶段 和 13 个关键步骤。
一、 生命周期全景图(核心流程)
为了直观理解,先看这张核心流程图:
1. 实例化 (Instantiation)
↓
2. 填充属性 (Populate Properties)
↓
3. 设置 Aware 接口 (Aware Interfaces)
↓
4. BeanPostProcessor 前置处理 (Before Initialization)
↓
5. 初始化 (Initialization)
├─ @PostConstruct
├─ InitializingBean.afterPropertiesSet()
└─ 自定义 init-method
↓
6. BeanPostProcessor 后置处理 (After Initialization)
↓
7. Bean 就绪 (Ready for Use)
↓
8. 销毁 (Destruction)
├─ @PreDestroy
├─ DisposableBean.destroy()
└─ 自定义 destroy-method
二、 详细步骤拆解
第一阶段:实例化与属性注入
| 步骤 | 名称 | 说明 |
|---|---|---|
| 1 | 实例化 Bean | 容器通过反射调用构造方法创建 Bean 实例(此时对象刚出生,属性全是默认值)。 |
| 2 | 设置属性值 (DI) | 容器解析配置(XML/@Component/@Bean),通过 Setter 或字段注入将依赖的 Bean 注入进来。 |
第二阶段:Aware 接口回调(感知容器)
如果 Bean 实现了 Aware 接口,Spring 会回调这些方法,让 Bean 感知到容器的存在。
| 步骤 | 接口 | 作用 |
|---|---|---|
| 3 | BeanNameAware | 获取 Bean 在容器中的 ID。 |
| 4 | BeanFactoryAware | 获取创建它的 BeanFactory。 |
| 5 | ApplicationContextAware | 获取 Spring 上下文(最常用,可获取环境配置等)。 |
第三阶段:初始化前置处理(BeanPostProcessor)
这是 Spring 扩展点的核心,允许在 Bean 初始化前后插入自定义逻辑(如 AOP 代理就是在这里生成的)。
| 步骤 | 名称 | 说明 |
|---|---|---|
| 6 | BeanPostProcessor.postProcessBeforeInitialization | 在所有初始化方法之前执行。例如 @PostConstruct 注解的处理器就是在此处生效。 |
第四阶段:初始化(Initialization)
这是 Bean 正式投入使用前的最后一步,用于校验配置或启动资源。
| 步骤 | 名称 | 说明 |
|---|---|---|
| 7 | @PostConstruct | JSR-250 标准注解,标注的方法会被调用。 |
| 8 | InitializingBean.afterPropertiesSet() | 实现该接口的 Bean 必须重写此方法。 |
| 9 | 自定义 init-method | XML 中 init-method 或 @Bean(initMethod="...") 指定的方法。 |
注意:如果同时存在,
@PostConstruct早于InitializingBean,早于init-method。
第五阶段:初始化后置处理(AOP 关键)
| 步骤 | 名称 | 说明 |
|---|---|---|
| 10 | BeanPostProcessor.postProcessAfterInitialization | 初始化完成后执行。Spring AOP 就是在此处创建代理对象并返回,替换原始对象。 |
第六阶段:使用与销毁
| 步骤 | 名称 | 说明 |
|---|---|---|
| 11 | Bean 就绪 | Bean 存储在单例池中,等待被程序调用。 |
| 12 | 销毁回调 | 容器关闭时触发,顺序与初始化相反: 1. @PreDestroy2. DisposableBean.destroy()3. 自定义 destroy-method |
三、 代码示例验证顺序
@Component
public class LifeCycleBean implements BeanNameAware, InitializingBean, DisposableBean {
public LifeCycleBean() {
System.out.println("1. 构造方法执行");
}
@Override
public void setBeanName(String name) {
System.out.println("2. BeanNameAware.setBeanName: " + name);
}
@PostConstruct
public void postConstruct() {
System.out.println("3. @PostConstruct");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("4. InitializingBean.afterPropertiesSet");
}
public void initMethod() {
System.out.println("5. 自定义 init-method");
}
@PreDestroy
public void preDestroy() {
System.out.println("6. @PreDestroy");
}
@Override
public void destroy() throws Exception {
System.out.println("7. DisposableBean.destroy");
}
public void destroyMethod() {
System.out.println("8. 自定义 destroy-method");
}
}
输出结果:
1. 构造方法执行
2. BeanNameAware.setBeanName: lifeCycleBean
3. @PostConstruct
4. InitializingBean.afterPropertiesSet
5. 自定义 init-method
...
6. @PreDestroy
7. DisposableBean.destroy
8. 自定义 destroy-method
四、 关键机制与面试考点
1. BeanPostProcessor 的作用域
BeanPostProcessor 是针对所有 Bean 生效的。如果你定义了多个 BeanPostProcessor,可以通过实现 Ordered 接口来控制执行顺序。
2. 循环依赖如何解决?
Spring 通过 三级缓存 解决单例 Bean 的循环依赖(Setter/Field 注入):
- 一级缓存:存放成品 Bean。
- 二级缓存:存放早期的 Bean 引用(未完成初始化的)。
- 三级缓存:存放 ObjectFactory(用于生成早期引用,特别是解决 AOP 代理问题)。
注意:构造器注入和多例(Prototype)模式无法解决循环依赖。
3. 单例 vs 原型 (Prototype)
- Singleton(默认):容器启动时创建,生命周期完全由容器管理,销毁时调用销毁方法。
- Prototype:每次获取时创建,容器只负责创建和初始化,不负责销毁,销毁方法需要用户自行调用。
五、 视野拓展:生命周期与 Spring Boot Starter
Spring Boot Starter 中生命周期相关:
- 自动配置类 (
XxxAutoConfiguration) 本质上就是一个@Configuration类,它内部定义的@Bean都会经历上述生命周期。 - 条件注解 (
@ConditionalOnMissingBean) 通常在 初始化阶段 之前生效,决定了某个 Bean 是否会被创建。 - 健康指示器 (
HealthIndicator) 或 指标收集器 通常在 初始化阶段 注册到监控系统中。
掌握 Bean 生命周期,是理解 Spring Boot 自动装配原理和进行高级扩展(如自定义 Starter、AOP 切面)的基础。

1万+

被折叠的 条评论
为什么被折叠?



