Spring Bean 的生命周期介绍
Spring Bean 的生命周期涉及多个阶段,从实例化到销毁,在开发中我们可以通过各种接口和注解介入这些阶段来定制化自己的功能。以下是详细的生命周期流程:
1. Bean 的实例化(Instantiation)
- 方式:通过构造函数或工厂方法创建 Bean 的实例。
- 触发条件:容器启动时,根据配置(如
@Component
、XML 配置等)创建 Bean。 - 关键点:此时 Bean 的属性尚未注入。
2. 属性赋值(Population of Properties)
- 依赖注入:通过
@Autowired
、Setter 方法、XML 配置的<property>
等方式注入依赖。 - 处理
@Value
:解析并注入外部化配置(如application.properties
)。
3. Aware 接口回调
Bean 可以通过实现 Aware
接口获取容器信息:
BeanNameAware
:获取 Bean 的名称。BeanFactoryAware
:获取BeanFactory
实例。ApplicationContextAware
:获取ApplicationContext
实例。EnvironmentAware
:获取环境变量和配置。
public class MyBean implements BeanNameAware {
@Override
public void setBeanName(String name) {
// 获取 Bean 的名称
}
}
4. BeanPostProcessor 的前置处理
- 接口:
BeanPostProcessor.postProcessBeforeInitialization()
- 作用:在初始化方法(如
@PostConstruct
)之前执行自定义逻辑。 - 典型应用:AOP 代理的生成、监控埋点等。
5. 初始化(Initialization)
初始化逻辑按顺序执行:
@PostConstruct
注解:JSR-250 标准,标记初始化方法。InitializingBean.afterPropertiesSet()
:Spring 提供的初始化接口。- 自定义
init-method
:通过 XML 或@Bean(initMethod = "init")
指定。
public class MyBean {
@PostConstruct
public void postConstruct() {
// 初始化逻辑
}
public void init() {
// XML 或 @Bean 指定的初始化方法
}
}
6. BeanPostProcessor 的后置处理
- 接口:
BeanPostProcessor.postProcessAfterInitialization()
- 作用:在初始化方法之后执行自定义逻辑。
- 典型应用:最终代理对象的包装(如 Spring AOP)。
7. Bean 就绪(Ready)
- 此时 Bean 已完全初始化,可被应用程序使用。
- 作用域影响:
- Singleton:容器中只有一个实例。
- Prototype:每次请求都生成新实例(销毁需手动处理)。
- 其他作用域(Request、Session 等):生命周期与会话或请求绑定。
8. 销毁(Destruction)
销毁逻辑按顺序执行:
@PreDestroy
注解:JSR-250 标准,标记销毁方法。DisposableBean.destroy()
:Spring 提供的销毁接口。- 自定义
destroy-method
:通过 XML 或@Bean(destroyMethod = "destroy")
指定。
public class MyBean {
@PreDestroy
public void preDestroy() {
// 销毁逻辑
}
public void destroy() {
// XML 或 @Bean 指定的销毁方法
}
}
完整生命周期流程图
实例化 → 属性注入 → Aware 接口 → BeanPostProcessor 前置处理 →
@PostConstruct → InitializingBean → init-method →
BeanPostProcessor 后置处理 → 使用中 →
@PreDestroy → DisposableBean → destroy-method
扩展点与注意事项
BeanFactoryPostProcessor
:- 在 Bean 定义加载后、实例化前修改 Bean 的定义(如修改属性值)。
BeanDefinitionRegistryPostProcessor
:- 更早阶段注册额外的 Bean 定义。
- 作用域差异:
- Prototype Bean 的销毁需手动调用
ctx.getBeanFactory().destroyBean(bean)
。
- Prototype Bean 的销毁需手动调用
- 循环依赖:
- 通过三级缓存解决(仅限 Singleton Bean)。
示例代码
public class LifecycleBean implements BeanNameAware, InitializingBean, DisposableBean {
private String name;
@Override
public void setBeanName(String name) {
this.name = name; // BeanNameAware 回调
}
@PostConstruct
public void postConstruct() {
System.out.println("@PostConstruct 方法");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean.afterPropertiesSet()");
}
public void customInit() {
System.out.println("自定义 init-method");
}
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy 方法");
}
@Override
public void destroy() {
System.out.println("DisposableBean.destroy()");
}
public void customDestroy() {
System.out.println("自定义 destroy-method");
}
}
通过理解 Spring Bean 的生命周期,我们可以更精准地控制 Bean 的初始化与销毁过程,优化资源管理和扩展框架功能。