当前位置: 首页 > news >正文

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 {​// 属性注入(此阶段执行)​@Autowired​private UserDao userDao;​​// Setter注入(此阶段执行setUserDao方法)​private OrderDao orderDao;​@Autowired​public 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;​@Override​public void setBeanName(String name) {​this.beanName = name; // 获取Bean名称​System.out.println("Bean名称:" + beanName);​}​@Override​public void setBeanFactory(BeanFactory factory) throws BeansException {​this.beanFactory = factory; // 获取BeanFactory​}​}​​

(2)执行BeanPostProcessor的前置处理(初始化前)​

BeanPostProcessor是 Spring 的扩展点接口,所有 Bean 在初始化前都会执行其postProcessBeforeInitialization方法,可用于对 Bean 进行增强处理(如 AOP 代理创建的前置准备)。​

示例代码:​

@Component​public class MyBeanPostProcessor implements BeanPostProcessor {​@Override​public 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注解​@PostConstruct​public void initByAnnotation() {​System.out.println("通过@PostConstruct初始化");​}​// 方式2:init-method配置(需在XML中指定init-method="initByMethod")​public void initByMethod() {​System.out.println("通过init-method初始化");​}​// 方式3:实现InitializingBean接口​@Override​public void afterPropertiesSet() throws Exception {​System.out.println("通过InitializingBean初始化");​}​}​​

执行顺序:@PostConstruct → InitializingBean.afterPropertiesSet() → init-method​

(4)执行BeanPostProcessor的后置处理(初始化后)​

BeanPostProcessor的postProcessAfterInitialization方法在初始化后执行,常用于对 Bean 进行最终增强(如 AOP 代理对象的创建)。​

示例代码:​

@Component​public class MyBeanPostProcessor implements BeanPostProcessor {​@Override​public 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注解​@PreDestroy​public void destroyByAnnotation() {​System.out.println("通过@PreDestroy销毁");​}​// 方式2:destroy-method配置​public void destroyByMethod() {​System.out.println("通过destroy-method销毁");​}​// 方式3:实现DisposableBean接口​@Override​public 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 生命周期后,我们可以在实际开发中灵活运用:​

  1. 资源初始化:在@PostConstruct或init-method中加载配置文件、初始化缓存(如 Redis 连接)​
  1. 依赖检查:在InitializingBean.afterPropertiesSet()中验证必要属性是否注入,避免空指针​
  1. AOP 增强:通过BeanPostProcessor在初始化前后对 Bean 进行代理(Spring AOP 的实现核心)​
  1. 资源释放:在@PreDestroy或destroy-method中关闭数据库连接、释放文件资源​
  1. 日志记录:在生命周期各阶段记录日志,便于问题排查​

五、总结​

Spring Bean 的生命周期是 Spring IoC 容器的核心机制,从实例化、属性注入、初始化到销毁,每个阶段都提供了丰富的扩展点。掌握生命周期的执行流程,不仅能帮助我们理解 Spring 的运行原理,更能在实际开发中利用生命周期回调函数编写更优雅、更可靠的代码。​

http://www.dtcms.com/a/336191.html

相关文章:

  • Gemini 学习记录:实践与反思
  • 深度解析 Spring Bean 生命周期
  • UE5多人MOBA+GAS 49、创建大厅
  • MariaDB 多源复制
  • Qt异步编程:QFuture与QPromise深度解析
  • Mysql常见的查询总结
  • Golang database/sql 包深度解析(二):连接池实现原理
  • 快速掌握Hardhat与Solidity智能合约开发
  • Rust Web 全栈开发(十三):发布
  • 实时视频延迟优化实战:RTSP与RTMP播放器哪个延迟更低?
  • 数据结构初阶(19)外排序·文件归并排序的实现
  • 博士招生 | 麻省理工学院 招收化学+人工智能方向 博士/博士后
  • 【编程实践】关于S3DIS数据集的问题
  • Docker+飞算JavaAI=未来:全流程容器化AI开发实战
  • Python注解
  • 【leetcode】14. 最长公共前缀
  • 构建经典PyTorch框架卷积神经网络参数demo
  • WPF真入门教程35--手搓WPF出真汁【蜀味正道CS版】
  • 中国三大主粮作物(水稻、小麦、玉米)空间分布数据集
  • Python开发环境
  • 密码学系列 - 零知识证明(ZKP) - 多种承诺方案
  • Windows Server SDN智能流量管理方案
  • 网络通信的基本概念与设备
  • 【力扣热题100】双指针—— 接雨水
  • Ubuntu22系统docker部署Dify【教程】
  • go资料汇总
  • 上网行为组网方案
  • 图论水题4
  • 隐私屏软件(支持win10以上系统)
  • Python异常、模块与包(五分钟小白从入门)