Spring Bean 的生命周期是指从 Bean 的创建、初始化到销毁的完整过程,Spring 提供了多个扩展点允许开发者介入这一过程。以下是 Bean 生命周期的完整流程和关键扩展点:
1. Bean 生命周期的核心阶段
Spring Bean 的生命周期可以分为以下几个主要阶段:
(1) Bean 的实例化(Instantiation)
-
触发条件:当容器启动或首次请求 Bean 时,Spring 通过反射或工厂方法创建Bean 实例。
-
底层机制:
-
如果 Bean 是单例(Singleton),默认在容器启动时初始化(除非配置
@Lazy
)。 -
如果 Bean 是原型(Prototype),每次请求时都会创建新实例。
-
(2) 属性赋值(Population)
-
依赖注入(DI):
-
通过
@Autowired
、@Value
、@Resource
注入属性。 -
如果存在循环依赖,Spring 使用三级缓存解决:
-
singletonFactories
(存放未完全初始化的 Bean) -
earlySingletonObjects
(存放提前暴露的 Bean) -
singletonObjects
(存放完全初始化的 Bean)。
-
-
(3) Aware 接口回调
-
作用:让 Bean 感知容器的某些组件(如
ApplicationContext
、BeanName
)。 -
常见
Aware
接口:-
BeanNameAware
(获取 Bean 的名称) -
BeanFactoryAware
(获取BeanFactory
) -
ApplicationContextAware
(获取ApplicationContext
) -
EnvironmentAware
(获取环境变量)
-
-
示例:
@Component
public class MyBean implements BeanNameAware, ApplicationContextAware {
@Override
public void setBeanName(String name) {
System.out.println("Bean name: " + name);
}
@Override
public void setApplicationContext(ApplicationContext context) {
System.out.println("ApplicationContext: " + context);
}
}
(4) BeanPostProcessor
前置处理
-
作用:在 Bean 初始化前后进行额外处理(如 AOP 代理、
@PostConstruct
调用)。 -
关键方法:
-
postProcessBeforeInitialization()
:初始化前调用。 -
postProcessAfterInitialization()
:初始化后调用。
-
-
示例:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("Before init: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("After init: " + beanName);
return bean;
}
}
(5) 初始化(Initialization)
-
触发方式:
-
@PostConstruct
注解的方法。 -
InitializingBean.afterPropertiesSet()
接口方法。 -
XML 配置的
init-method
。
-
-
示例:
@Component
public class MyBean implements InitializingBean {
@PostConstruct
public void init() {
System.out.println("@PostConstruct called");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean.afterPropertiesSet() called");
}
public void customInit() {
System.out.println("Custom init-method called");
}
}
(6) BeanPostProcessor
后置处理
-
典型应用:
-
AOP 动态代理(
AbstractAutoProxyCreator
)。 -
事务管理(
InfrastructureAdvisorAutoProxyCreator
)。
-
(7) Bean 就绪(Ready)
-
单例 Bean:存入
singletonObjects
缓存,供后续使用。 -
原型 Bean:每次请求时重新创建。
(8) 销毁(Destruction)
-
触发方式:
-
@PreDestroy
注解的方法。 -
DisposableBean.destroy()
接口方法。 -
XML 配置的
destroy-method
。
-
-
示例:
@Component
public class MyBean implements DisposableBean {
@PreDestroy
public void cleanup() {
System.out.println("@PreDestroy called");
}
@Override
public void destroy() {
System.out.println("DisposableBean.destroy() called");
}
public void customDestroy() {
System.out.println("Custom destroy-method called");
}
}
2. 完整的生命周期流程图
A[Bean 实例化] --> B[属性赋值(依赖注入)]
B --> C[Aware 接口回调]
C --> D[BeanPostProcessor 前置处理]
D --> E[初始化(@PostConstruct/afterPropertiesSet/init-method)]
E --> F[BeanPostProcessor 后置处理]
F --> G[Bean 就绪]
G --> H[容器关闭]
H --> I[销毁(@PreDestroy/destroy/destroy-method)]
3. 关键扩展点总结
扩展点 | 触发时机 | 典型应用场景 |
---|---|---|
BeanFactoryPostProcessor | Bean 定义加载后,实例化前 | 修改 Bean 定义(如占位符替换) |
BeanPostProcessor | Bean 初始化前后 | AOP 代理、注解处理(如 @Autowired ) |
InitializingBean | 属性注入完成后 | 自定义初始化逻辑 |
DisposableBean | 容器关闭时 | 资源释放(如关闭文件句柄) |
4. 常见问题
(1) @PostConstruct
vs InitializingBean
vs init-method
-
执行顺序:
-
@PostConstruct
-
InitializingBean.afterPropertiesSet()
-
init-method
-
-
推荐:优先使用
@PostConstruct
(更符合注解驱动编程风格)。
(2) 如何避免循环依赖?
-
使用
@Lazy
延迟加载。 -
避免字段注入,改用构造器注入:
@Component
public class ServiceA {
private final ServiceB serviceB;
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
(3) 如何手动销毁 Bean?
-
对于原型 Bean,Spring 不会自动销毁,需手动调用
destroy()
:
5. 最佳实践
-
避免在初始化阶段执行耗时操作,防止应用启动变慢。
-
优先使用
@PostConstruct
和@PreDestroy
,而非InitializingBean
/DisposableBean
。 -
谨慎使用
Aware
接口,避免与容器强耦合。 -
合理使用
BeanPostProcessor
,适用于框架级扩展(如 AOP)。