Spring Bean 的生命周期:从创建到销毁的完整旅程
在 Spring 框架中,Bean 作为核心组件,其生命周期管理是 Spring IoC 容器的核心功能之一。理解 Bean 的生命周期,不仅能帮助我们更好地掌握 Spring 的运行机制,还能在实际开发中合理利用生命周期回调函数处理业务逻辑。本文将详细解析 Spring Bean 的完整生命周期,从创建到销毁的每个阶段都进行深入讲解。
一、Spring Bean 生命周期概述
Spring Bean 的生命周期是指从 Bean 被 Spring 容器创建开始,到 Bean 最终被销毁的全过程。整个生命周期由 Spring IoC 容器全程管理,开发者可以通过特定的接口或注解介入生命周期的各个阶段。
简单来说,Spring Bean 的生命周期可分为以下4 个大阶段和7 个关键节点:
- 实例化阶段:创建 Bean 的实例对象
- 属性注入阶段:为 Bean 的属性设置值(依赖注入)
- 初始化阶段:执行初始化逻辑(如数据加载、资源初始化)
- 销毁阶段:容器关闭时执行清理逻辑(如释放资源)
二、生命周期各阶段详解
1. 实例化(Instantiation)
阶段目标:创建 Bean 的实例对象,相当于执行了new操作。
核心逻辑:Spring 容器根据 Bean 的定义(如类路径、构造方法),通过反射机制调用 Bean 的构造方法创建实例。此时 Bean 的属性尚未赋值,处于 "毛坯状态"。
注意点:
- 若 Bean 存在多个构造方法,Spring 会根据参数匹配选择合适的构造方法(如通过@Autowired指定或默认无参构造)
- 实例化仅创建对象本身,不涉及任何属性设置或业务逻辑
2. 属性注入(Population)
阶段目标:为 Bean 的属性赋值,完成依赖注入(DI)。
核心逻辑:Spring 容器根据 Bean 定义中的依赖关系,将容器中已创建的其他 Bean 注入到当前 Bean 的属性中。注入方式包括:
- 构造器注入(实例化阶段已完成)
- Setter 方法注入(此阶段执行)
- 字段注入(通过反射直接赋值)
示例代码:
public class UserService {// 属性注入(此阶段执行)@Autowiredprivate UserDao userDao;// Setter注入(此阶段执行setUserDao方法)private OrderDao orderDao;@Autowiredpublic void setOrderDao(OrderDao orderDao) {this.orderDao = orderDao;}
}
3. 初始化(Initialization)
初始化阶段是 Bean 生命周期中最灵活的阶段,开发者可通过多种方式介入,执行自定义逻辑。此阶段包含3 个关键节点:
(1)执行BeanNameAware和BeanFactoryAware接口
- BeanNameAware:通过setBeanName(String name)方法获取 Bean 在容器中的 ID(名称)
- BeanFactoryAware:通过setBeanFactory(BeanFactory factory)方法获取当前 BeanFactory 容器
示例代码:
public class UsService implements BeanNameAware, BeanFactoryAware {private String beanName;private BeanFactory beanFactory;@Overridepublic void setBeanName(String name) {this.beanName = name; // 获取Bean名称System.out.println("Bean名称:" + beanName);}@Overridepublic void setBeanFactory(BeanFactory factory) throws BeansException {this.beanFactory = factory; // 获取BeanFactory}}
(2)执行BeanPostProcessor的前置处理(初始化前)
BeanPostProcessor是 Spring 的扩展点接口,所有 Bean 在初始化前都会执行其postProcessBeforeInitialization方法,可用于对 Bean 进行增强处理(如 AOP 代理创建的前置准备)。
示例代码:
@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 初始化前的处理逻辑if (bean instanceof UserService) {System.out.println("UserService初始化前增强");}return bean; // 返回处理后的Bean}}
(3)执行自定义初始化方法(初始化)
开发者可通过以下 3 种方式定义初始化方法,Spring 会在此时执行:
- @PostConstruct注解:标注在方法上,容器会自动识别
- init-method配置:在 XML 配置中通过<bean init-method="init"/>指定
- 实现InitializingBean接口:重写afterPropertiesSet()方法
示例代码:
public class UserService implements InitializingBean {// 方式1:@PostConstruct注解@PostConstructpublic void initByAnnotation() {System.out.println("通过@PostConstruct初始化");}// 方式2:init-method配置(需在XML中指定init-method="initByMethod")public void initByMethod() {System.out.println("通过init-method初始化");}// 方式3:实现InitializingBean接口@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("通过InitializingBean初始化");}}
执行顺序:@PostConstruct → InitializingBean.afterPropertiesSet() → init-method
(4)执行BeanPostProcessor的后置处理(初始化后)
BeanPostProcessor的postProcessAfterInitialization方法在初始化后执行,常用于对 Bean 进行最终增强(如 AOP 代理对象的创建)。
示例代码:
@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 初始化后的处理逻辑if (bean instanceof UserService) {System.out.println("UserService初始化后增强");}return bean; // 返回增强后的Bean(如代理对象)}}
4. 就绪与使用阶段
初始化完成后,Bean 进入 "就绪" 状态,此时 Bean 已完全可用,开发者可通过ApplicationContext.getBean()方法获取 Bean 并使用。
在此阶段,Bean 会一直存在于 Spring 容器中,直到容器关闭。单例 Bean(默认)会伴随容器全程,多例 Bean 则在每次获取时创建新实例,使用后由 JVM 垃圾回收器回收。
5. 销毁(Destruction)
当 Spring 容器关闭时,Bean 进入销毁阶段,主要执行资源清理逻辑。此阶段包含2 个关键节点:
(1)执行自定义销毁方法
与初始化方法对应,销毁方法也有 3 种定义方式:
- @PreDestroy注解:标注在方法上
- destroy-method配置:在 XML 中通过<bean destroy-method="destroy"/>指定
- 实现DisposableBean接口:重写destroy()方法
示例代码:
public class UserService implements DisposableBean {// 方式1:@PreDestroy注解@PreDestroypublic void destroyByAnnotation() {System.out.println("通过@PreDestroy销毁");}// 方式2:destroy-method配置public void destroyByMethod() {System.out.println("通过destroy-method销毁");}// 方式3:实现DisposableBean接口@Overridepublic void destroy() throws Exception {System.out.println("通过DisposableBean销毁");}}
执行顺序:@PreDestroy → DisposableBean.destroy() → destroy-method
(2)容器关闭清理
容器关闭时,会调用所有单例 Bean 的销毁方法,释放资源(如数据库连接、文件流等)。多例 Bean 由于由 JVM 管理,Spring 容器不会主动调用其销毁方法。
三、生命周期执行顺序总结
为了更清晰地掌握 Bean 生命周期的执行顺序,我们通过一个完整示例的输出结果来总结:
// 实例化阶段
创建UserService实例
// 属性注入阶段
注入userDao属性
注入orderDao属性
// 初始化阶段 - Aware接口
执行setBeanName() → Bean名称:userService
执行setBeanFactory() → 获取BeanFactory
// 初始化阶段 - BeanPostProcessor前置
执行postProcessBeforeInitialization() → UserService初始化前增强
// 初始化阶段 - 自定义初始化
执行@PostConstruct方法 → 通过@PostConstruct初始化
执行InitializingBean.afterPropertiesSet() → 通过InitializingBean初始化
执行init-method方法 → 通过init-method初始化
// 初始化阶段 - BeanPostProcessor后置
执行postProcessAfterInitialization() → UserService初始化后增强
// 就绪阶段
UserService已就绪,可通过容器获取使用
// 销毁阶段
容器关闭...
执行@PreDestroy方法 → 通过@PreDestroy销毁
执行DisposableBean.destroy() → 通过DisposableBean销毁
执行destroy-method方法 → 通过destroy-method销毁
四、实际开发中的应用场景
理解 Bean 生命周期后,我们可以在实际开发中灵活运用:
- 资源初始化:在@PostConstruct或init-method中加载配置文件、初始化缓存(如 Redis 连接)
- 依赖检查:在InitializingBean.afterPropertiesSet()中验证必要属性是否注入,避免空指针
- AOP 增强:通过BeanPostProcessor在初始化前后对 Bean 进行代理(Spring AOP 的实现核心)
- 资源释放:在@PreDestroy或destroy-method中关闭数据库连接、释放文件资源
- 日志记录:在生命周期各阶段记录日志,便于问题排查
五、总结
Spring Bean 的生命周期是 Spring IoC 容器的核心机制,从实例化、属性注入、初始化到销毁,每个阶段都提供了丰富的扩展点。掌握生命周期的执行流程,不仅能帮助我们理解 Spring 的运行原理,更能在实际开发中利用生命周期回调函数编写更优雅、更可靠的代码。