当前位置: 首页 > 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.lryc.cn/news/623903.html

相关文章:

  • 好看的个人导航系统多模板带后台
  • React端到端测试
  • 通达信【牛股妖股埋伏】副图+选股指标
  • Shell脚本-while循环应用案例
  • nn.Module模块介绍
  • 计算机视觉(一):nvidia与cuda介绍
  • OpenMemory MCP发布!AI记忆本地共享,Claude、Cursor一键同步效率翻倍!
  • 【Linux】文件基础IO
  • Agent开发进阶路线:从基础响应到自主决策的架构演进
  • Python使用数据类dataclasses管理数据对象
  • 【C2000】C2000例程使用介绍
  • Python进行中文分词
  • MySQL定时任务详解 - Event Scheduler 事件调度器从基础到实战
  • Blender模拟结构光3D Scanner(二)投影仪内参数匹配
  • 火狐(Mozilla Firefox)浏览器离线安装包下载
  • 学习Python中Selenium模块的基本用法(5:程序基本步骤)
  • Python数据类型转换详解:从基础到实践
  • Python 基础语法(二)
  • 0️⃣基础 认识Python操作文件夹(初学者)
  • Linux:TCP协议
  • RK3568平台开发系列讲解:PCIE trainning失败怎么办
  • 深入解析函数指针及其数组、typedef关键字应用技巧
  • 0-12岁幼儿启蒙与教育
  • CF2121C Those Who Are With Us
  • 2001-2024年中国玉米种植分布数据集
  • 【牛客刷题】01字符串按递增长度截取并转换为十进制数值
  • Day07 缓存商品 购物车
  • 14.web api 5
  • LEA(Load Effective Address)指令
  • 19.5 「4步压缩大模型:GPTQ量化实战让OPT-1.3B显存直降75%」