Spring Bean 生命周期详解
Spring Bean 的生命周期是 Spring IoC 容器管理 Bean 对象从创建到销毁的整个过程。理解 Bean 的生命周期对于深入掌握 Spring 框架至关重要。下面将详细介绍 Spring Bean 的完整生命周期。
一、Bean 生命周期概览
Spring Bean 的生命周期可以分为以下主要阶段:
- 实例化(Instantiation)
- 属性赋值(Populate Properties)
- 初始化(Initialization)
- 使用(In Use)
- 销毁(Destruction)
二、详细生命周期阶段
1. 实例化(Instantiation)
实例化是创建 Bean 对象的第一步,Spring 容器通过反射机制创建 Bean 的实例。
- 对于 XML 配置,Spring 从
<bean>
标签中读取class
属性 - 对于注解配置,Spring 通过
@Component
等注解找到对应的类 - 使用构造函数创建 Bean 实例
2. 属性赋值(Populate Properties)
在实例化后,Spring 容器将为 Bean 注入配置的属性值和依赖的其他 Bean。
- XML 配置中的
<property>
或<constructor-arg>
标签 - 注解配置中的
@Autowired
、@Resource
等注解 - setter 方法注入或构造函数注入
3. 初始化(Initialization)
初始化阶段是 Bean 准备就绪前的最后一步,包含多个回调方法的执行。按照执行顺序:
3.1 Aware 接口回调
Spring 提供了一系列的 Aware 接口,用于让 Bean 获取 Spring 容器的特定资源:
- BeanNameAware :通过
setBeanName(String name)
方法获取 Bean 在容器中的名称 - BeanClassLoaderAware :通过
setBeanClassLoader(ClassLoader classLoader)
方法获取加载 Bean 的类加载器 - BeanFactoryAware :通过
setBeanFactory(BeanFactory beanFactory)
方法获取 BeanFactory 容器实例 - ApplicationContextAware :通过
setApplicationContext(ApplicationContext applicationContext)
方法获取 ApplicationContext 容器实例
3.2 BeanPostProcessor 前置处理
BeanPostProcessor
接口的 postProcessBeforeInitialization(Object bean, String beanName)
方法在初始化前被调用,可以对 Bean 进行加工处理。
3.3 初始化回调
- InitializingBean 接口 :实现该接口的 Bean 会调用
afterPropertiesSet()
方法 - 自定义 init-method :通过 XML 的
init-method
属性或@Bean
注解的initMethod
属性指定的初始化方法
3.4 BeanPostProcessor 后置处理
BeanPostProcessor
接口的 postProcessAfterInitialization(Object bean, String beanName)
方法在初始化后被调用,可以对初始化完成的 Bean 进行最后的加工处理。
4. 使用(In Use)
初始化完成后,Bean 就可以被应用程序使用了。
- 单例(Singleton)Bean:容器启动时就完成实例化和初始化,一直存在直到容器关闭
- 原型(Prototype)Bean:每次请求时创建新实例,使用完后由客户端负责销毁
5. 销毁(Destruction)
当容器关闭时,对于单例 Bean,会执行销毁操作:
- DisposableBean 接口 :实现该接口的 Bean 会调用
destroy()
方法 - 自定义 destroy-method :通过 XML 的
destroy-method
属性或@Bean
注解的destroyMethod
属性指定的销毁方法
三、生命周期流程图
scss
实例化 (创建Bean对象)
↓
属性赋值 (注入依赖)
↓
Aware接口回调
↓
BeanPostProcessor.postProcessBeforeInitialization()
↓
InitializingBean.afterPropertiesSet()
↓
自定义init-method
↓
BeanPostProcessor.postProcessAfterInitialization()
↓
Bean就绪,可以使用
↓
容器关闭
↓
DisposableBean.destroy()
↓
自定义destroy-method
四、Bean 生命周期与作用域的关系
不同作用域的 Bean 在生命周期上有显著差异:
单例(Singleton)Bean
- 容器启动时创建(除非配置了懒加载)
- 容器关闭时销毁
- 整个应用程序共享同一个实例
原型(Prototype)Bean
- 每次请求时创建
- Spring 容器只负责创建,不负责销毁
- 销毁由客户端代码负责
Web 相关作用域
- request:每个 HTTP 请求创建一个实例,请求结束时销毁
- session:每个 HTTP 会话创建一个实例,会话结束时销毁
- application:整个 Web 应用创建一个实例,应用关闭时销毁
五、实际应用示例
下面通过代码示例来说明如何使用 Bean 生命周期回调:
示例1:实现生命周期接口
java
public class LifecycleBean implements
BeanNameAware,
BeanFactoryAware,
InitializingBean,
DisposableBean {
private String beanName;
private BeanFactory beanFactory;
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("BeanNameAware: 设置Bean名称为 " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
System.out.println("BeanFactoryAware: 设置BeanFactory");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean: 属性设置完成后执行初始化");
}
// 自定义初始化方法
public void customInit() {
System.out.println("自定义初始化方法: customInit");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean: 执行销毁操作");
}
// 自定义销毁方法
public void customDestroy() {
System.out.println("自定义销毁方法: customDestroy");
}
}
示例2:使用 BeanPostProcessor
java
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor前置处理: " + beanName);
// 可以对bean进行修改或替换
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor后置处理: " + beanName);
// 可以对bean进行修改或替换
return bean;
}
}
示例3:XML 配置生命周期方法
xml
<bean id="lifecycleBean"
class="com.example.LifecycleBean"
init-method="customInit"
destroy-method="customDestroy"/>
<bean class="com.example.CustomBeanPostProcessor"/>
示例4:Java 配置生命周期方法
java
@Configuration
public class AppConfig {
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public LifecycleBean lifecycleBean() {
return new LifecycleBean();
}
@Bean
public CustomBeanPostProcessor customBeanPostProcessor() {
return new CustomBeanPostProcessor();
}
}
六、在本项目中的体现
虽然当前项目没有直接实现所有生命周期接口,但项目中的配置和测试仍然体现了 Bean 生命周期的核心概念:
-
Bean 定义与实例化:通过 XML 和 Java 配置定义 Bean
-
属性赋值:如 applicationContext.xml中的构造函数注入:
xml<constructor-arg name="id" value="200"/> <constructor-arg name="username" value="xml-admin"/>
-
Bean 作用域:在config/BeanFactoryConfig.java 中定义了单例和原型 Bean
-
作用域测试:在 BeanFactoryTest.java 中测试了单例和原型作用域
七、最佳实践
-
优先使用接口回调 :实现
InitializingBean
和DisposableBean
接口比自定义 init/destroy 方法更直接 -
使用 JSR-250 注解 :Spring 支持标准的
@PostConstruct
和@PreDestroy
注解,它们不耦合于 Spring 框架 -
谨慎使用 BeanPostProcessor:它会影响所有 Bean,确保处理逻辑高效且正确
-
注意原型 Bean 的销毁:Spring 容器不负责销毁原型 Bean,需要客户端代码管理
-
避免在初始化方法中做耗时操作:这会延长容器启动时间
八、总结
Spring Bean 的生命周期是一个精心设计的流程,通过一系列的回调方法,允许开发者在 Bean 的不同阶段执行自定义逻辑。掌握 Bean 的生命周期对于开发健壮的 Spring 应用程序非常重要,可以帮助开发者更好地控制 Bean 的创建、配置和销毁过程,从而实现更灵活和强大的功能。