Bean 的生命周期详解
在 Spring 框架中,Bean 的生命周期是一个非常重要的概念。理解 Bean 的生命周期有助于我们更好地使用 Spring,包括如何初始化资源、如何清理资源以及如何自定义 Bean 的创建过程。
一、Bean 生命周期的核心阶段
Spring 容器中 Bean 的生命周期可以概括为以下几个主要阶段:
- 实例化:创建 Bean 的实例(通过构造器或工厂方法)
- 属性赋值:设置 Bean 的属性值(依赖注入)
- 初始化:执行初始化方法
- 使用:Bean 可以被应用程序使用
- 销毁:容器关闭时执行销毁方法
二、生命周期的详细过程
下面是一个更详细的流程图,展示了 Bean 从创建到销毁的完整过程:
plaintext
Bean定义注册到容器 → 实例化Bean → 填充属性 →
实现Aware接口的方法调用 → BeanPostProcessor前置处理 →
初始化方法调用 → BeanPostProcessor后置处理 →
Bean就绪可以使用 → 容器关闭 → 销毁方法调用
三、关键接口和方法
1. 实例化相关
- InstantiationAwareBeanPostProcessor:
- 可以在实例化前和实例化后进行干预
- 方法:
postProcessBeforeInstantiation和postProcessAfterInstantiation
2. 属性赋值相关
- AutowiredAnnotationBeanPostProcessor:
- 处理 @Autowired、@Resource 等注解
- CommonAnnotationBeanPostProcessor:
- 处理 JSR-250 注解如 @PostConstruct、@PreDestroy
3. Aware 接口
Spring 提供了一系列 Aware 接口,允许 Bean 获取容器的相关信息:
- BeanNameAware:获取 Bean 在容器中的名称
- BeanFactoryAware:获取 BeanFactory
- ApplicationContextAware:获取 ApplicationContext
- ResourceLoaderAware:获取资源加载器
- ServletContextAware(仅 Web 应用):获取 ServletContext
4. 初始化相关
初始化方法可以通过以下三种方式指定:
- 实现 InitializingBean 接口:java
public class MyBean implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { // 初始化逻辑 } } - 使用 @PostConstruct 注解:java
public class MyBean { @PostConstruct public void init() { // 初始化逻辑 } } - 在 XML 配置或 @Bean 注解中指定 init-method:java
@Bean(initMethod = "init") public MyBean myBean() { return new MyBean(); }
5. BeanPostProcessor
BeanPostProcessor 允许在 Bean 初始化前后进行额外处理:
java
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在初始化方法调用前执行
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 在初始化方法调用后执行
return bean;
}
}
6. 销毁相关
销毁方法可以通过以下三种方式指定:
- 实现 DisposableBean 接口:java
public class MyBean implements DisposableBean { @Override public void destroy() throws Exception { // 资源释放逻辑 } } - 使用 @PreDestroy 注解:java
public class MyBean { @PreDestroy public void cleanup() { // 资源释放逻辑 } } - 在 XML 配置或 @Bean 注解中指定 destroy-method:java
@Bean(destroyMethod = "cleanup") public MyBean myBean() { return new MyBean(); }
四、自定义生命周期处理器
除了上述标准方法外,还可以通过以下方式自定义 Bean 的生命周期:
1. BeanFactoryPostProcessor
允许在 Bean 定义加载后但实例化前修改 Bean 定义:
java
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 修改Bean定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("myBean");
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
}
2. DestructionAwareBeanPostProcessor
可以在 Bean 销毁前进行额外处理:
java
@Component
public class MyDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
// 在销毁前执行
}
@Override
public boolean requiresDestruction(Object bean) {
return true;
}
}
五、示例代码
下面是一个完整的示例,展示了一个 Bean 的生命周期:
java
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
private String name;
private ApplicationContext applicationContext;
// 构造器
public MyBean() {
System.out.println("MyBean: 构造器被调用");
}
// Setter方法(依赖注入)
public void setName(String name) {
System.out.println("MyBean: 设置name属性");
this.name = name;
}
// BeanNameAware接口方法
@Override
public void setBeanName(String beanName) {
System.out.println("MyBean: 实现BeanNameAware,获取bean名称: " + beanName);
}
// ApplicationContextAware接口方法
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("MyBean: 实现ApplicationContextAware,获取应用上下文");
this.applicationContext = applicationContext;
}
// @PostConstruct注解的初始化方法
@PostConstruct
public void postConstructInit() {
System.out.println("MyBean: @PostConstruct注解的初始化方法被调用");
}
// InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("MyBean: 实现InitializingBean,afterPropertiesSet方法被调用");
}
// 自定义初始化方法
public void customInit() {
System.out.println("MyBean: 自定义init-method方法被调用");
}
// @PreDestroy注解的销毁方法
@PreDestroy
public void preDestroy() {
System.out.println("MyBean: @PreDestroy注解的销毁方法被调用");
}
// DisposableBean接口方法
public void destroy() throws Exception {
System.out.println("MyBean: 实现DisposableBean,destroy方法被调用");
}
// 自定义销毁方法
public void customDestroy() {
System.out.println("MyBean: 自定义destroy-method方法被调用");
}
// 业务方法
public void doSomething() {
System.out.println("MyBean: 执行doSomething方法");
}
}
配置类:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public MyBean myBean() {
MyBean bean = new MyBean();
bean.setName("TestBean");
return bean;
}
}
六、生命周期总结
Bean 的完整生命周期可以概括为:
- 实例化:通过构造器创建 Bean 对象
- 依赖注入:设置 Bean 的属性值
- Aware 接口回调:如果实现了 Aware 接口,调用相应的方法
- BeanPostProcessor 前置处理:调用所有注册的 BeanPostProcessor 的前置处理方法
- 初始化方法调用:按顺序调用 @PostConstruct、InitializingBean 接口方法、自定义初始化方法
- BeanPostProcessor 后置处理:调用所有注册的 BeanPostProcessor 的后置处理方法
- Bean 就绪使用:Bean 可以被应用程序使用
- 容器关闭:当容器关闭时,调用销毁方法
- 销毁方法调用:按顺序调用 @PreDestroy、DisposableBean 接口方法、自定义销毁方法
理解 Bean 的生命周期有助于我们更好地控制 Spring Bean 的创建和销毁过程,正确地初始化资源和释放资源