本文目录导读:

Spring Bean 的生命周期是指 Bean 从创建到销毁的全过程,这个过程由 Spring IoC 容器管理。
为了让你直观理解,可以把 Bean 生命周期抽象为四个主要阶段: 实例化 -> 属性赋值 -> 初始化 -> 销毁
下面我为你详细拆解这个过程,并重点说明“初始化”和“销毁”的多种实现方式。
Bean 生命周期流程图(核心)
graph TD
A[加载 Bean 定义] --> B(实例化 Bean)
B --> C{属性赋值 / DI}
C --> D[设置 Bean Name / BeanFactory 等 Aware 接口]
D --> E[BeanPostProcessor - postProcessBeforeInitialization]
E --> F{执行初始化}
F --> G[@PostConstruct]
G --> H[InitializingBean - afterPropertiesSet]
H --> I[自定义 init-method]
I --> J[BeanPostProcessor - postProcessAfterInitialization]
J --> K{Bean 准备就绪 / 使用}
K -- 容器关闭 --> L{执行销毁}
L --> M[@PreDestroy]
M --> N[DisposableBean - destroy]
N --> O[自定义 destroy-method]
O --> P[销毁完成]
详细阶段解析
实例化(Instantiation)
- 动作:通过反射调用构造器创建 Bean 的实例。
- 关键点:Bean 的属性都还是默认值(null 或 0)。
属性赋值(Populate Properties / Dependency Injection)
- 动作:Spring 自动注入 Bean 中声明了
@Autowired、@Value、@Resource等注解的属性,或者在 XML/Config 中配置的属性。 - 关键点:Bean 才真正拥有“数据”。
初始化前(Aware 接口回调)
- 动作:Bean 实现了某些 Aware 接口,Spring 会调用对应的 setter 方法,把容器相关信息注入给 Bean。
- 常见接口:
BeanNameAware:设置 Bean 在容器中的名称。BeanFactoryAware:设置 BeanFactory 容器。ApplicationContextAware:设置 ApplicationContext 上下文(常用,可用来获取其他 Bean)。
初始化前处理(BeanPostProcessor -> postProcessBeforeInitialization)
- 动作:Spring 内置或你自定义的
BeanPostProcessor的postProcessBeforeInitialization方法会被调用。 - 用途:这是一个全局拦截器,可以对所有 Bean 在初始化之前进行加工。
- 流行应用:
@Autowired注解的底层实现(AutowiredAnnotationBeanPostProcessor)就在这里工作。
初始化(Initialization)
这是开发者最常控制的阶段,有三种方式(按执行顺序):
| 顺序 | 方式 | 描述 | 特点 |
|---|---|---|---|
| 第一 | @PostConstruct 注解 |
在方法上加注解 | Java 标准注解(JSR-250),推荐使用 |
| 第二 | InitializingBean 接口 |
实现 afterPropertiesSet() 方法 |
Spring 专属接口,与 Spring 耦合 |
| 第三 | init-method 配置 |
在 @Bean(initMethod=“方法名”) 或 XML 中指定 |
适合在配置类中指定 |
注意:这三种方式可以共存,Spring 会严格按照上述顺序执行。
初始化后处理(BeanPostProcessor -> postProcessAfterInitialization)
- 动作:
BeanPostProcessor的postProcessAfterInitialization方法被调用。 - 用途:这是创建 Bean 代理对象的最佳时机。
- 流行应用:AOP(
AbstractAutoProxyCreator)在这里为 Bean 创建 JDK 动态代理或 CGLIB 代理。
Bean 就绪
- 经过以上步骤,Bean 被放入 Spring 容器的“单例池”(Singleton Objects)中,可以供其他代码使用了。
销毁(Destruction)
当容器关闭时(例如调用 context.close()),会按照逆序执行销毁逻辑,同样有三种方式:
| 顺序 | 方式 | 描述 | 特点 |
|---|---|---|---|
| 第一 | @PreDestroy 注解 |
在方法上加注解 | Java 标准注解(JSR-250),推荐使用 |
| 第二 | DisposableBean 接口 |
实现 destroy() 方法 |
Spring 专属接口,与 Spring 耦合 |
| 第三 | destroy-method 配置 |
在 @Bean(destroyMethod=“方法名”) 或 XML 中指定 |
适合在配置类中指定 |
实战代码示例
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements InitializingBean, DisposableBean,
BeanNameAware, ApplicationContextAware {
private String beanName;
private ApplicationContext applicationContext;
// 1. 构造器 (实例化)
public MyBean() {
System.out.println("1. 构造器: 实例化 Bean");
}
// 2. 属性赋值 (略,假设有 @Autowired)
// 3. Aware 接口回调
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("3. Aware: BeanNameAware -> " + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
System.out.println("3. Aware: ApplicationContextAware");
}
// 5. 初始化阶段
// 第一种方式:@PostConstruct (最推荐)
@PostConstruct
public void customInitAnnotation() {
System.out.println("5.1 初始化: @PostConstruct");
}
// 第二种方式:InitializingBean 接口
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("5.2 初始化: InitializingBean.afterPropertiesSet()");
}
// 第三种方式:init-method (假设在配置中指定了 @Bean(initMethod = "customInitMethod"))
// 如果配置了,会在此处执行,但为了简洁,这里不重复展示
// 8. 销毁阶段
// 第一种方式:@PreDestroy (最推荐)
@PreDestroy
public void customDestroyAnnotation() {
System.out.println("8.1 销毁: @PreDestroy");
}
// 第二种方式:DisposableBean 接口
@Override
public void destroy() throws Exception {
System.out.println("8.2 销毁: DisposableBean.destroy()");
}
// 第三种方式:destroy-method (类似 init-method)
/**
* 业务方法
*/
public void doSomething() {
System.out.println("7. Bean 就绪: 执行业务逻辑");
}
}
// 配置类 (需要开启注解扫描)
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// 如果使用 @Bean 方式,可以指定 initMethod 和 destroyMethod
@Bean(initMethod = "customInitMethod", destroyMethod = "customDestroyMethod")
public AnotherBean anotherBean() {
return new AnotherBean();
}
}
BeanPostProcessor 与 BeanFactoryPostProcessor 的区别
这是面试常考点,也是容易混淆的地方。
| 特性 | BeanPostProcessor |
BeanFactoryPostProcessor |
|---|---|---|
| 执行时机 | Bean 实例化之后,初始化前后执行 | Bean 实例化之前,Bean 定义加载之后执行 |
| 操作对象 | Bean 实例(可以修改Bean的属性或返回代理对象) | BeanDefinition(可以修改Bean的定义,如作用域、属性值) |
| 典型应用 | AOP、@Autowired、属性填充 |
PropertySourcesPlaceholderConfigurer(解析占位符) |
BeanPostProcessor:是用来“加工” Bean 对象的。BeanFactoryPostProcessor:是用来“修改” Bean 配置元数据的。
高频面试题
-
JSR250 规范的生命周期注解是什么?
@PostConstruct和@PreDestroy。
-
Spring 如何保证 Bean 初始化顺序?
- 实现
Ordered接口或使用@Order注解(主要针对集合注入、BeanPostProcessor排序)。 - 使用
@DependsOn注解强制指定依赖的 Bean 先初始化。
- 实现
-
BeanPostProcessor和Aware接口的执行顺序是怎样的?- 先执行
Aware接口回调(设置 Bean Name、Context)。 - 再执行
BeanPostProcessor.postProcessBeforeInitialization。 - 然后执行初始化方法(
@PostConstruct->InitializingBean->init-method)。 - 最后执行
BeanPostProcessor.postProcessAfterInitialization。
- 先执行
-
如果一个 Bean 在 DI 时发生循环依赖,Spring 如何处理?
- 三级缓存机制:Spring 通过提前暴露半成品 Bean(
ObjectFactory)来解决单例模式下 setter 注入的循环依赖。构造器注入的循环依赖无法解决,只能报错。
- 三级缓存机制:Spring 通过提前暴露半成品 Bean(