Spring Bean:生命周期全景深度分析 / Spring 容器管理对象(Bean)
Bean 就是被 Spring IoC 容器统一创建、管理、赋值、初始化、销毁的 Java 对象。
Spring IoC 容器核心职责是统一管理 Bean 对象,从对象创建、依赖注入、初始化、业务使用到最终资源销毁的整套流程,即为Bean 生命周期。本文结合执行顺序、实现方式、作用域差异、面试考点,以多表格结构化全景拆解,覆盖简化流程、完整细粒度流程、初始化 / 销毁实现方案、单多例生命周期区别、高频实操案例。
普通 new 对象:程序员自己
new,自己管生命周期,Spring 不管。Spring Bean 对象:程序员只负责定义类,全权交给 Spring 容器托管,从创建、赋值、初始化到销毁全自动化。
一、Bean 生命周期两大版本总览
表 1:极简五阶段流程(文档基础版)
图片中展示的简化流程,适合入门记忆,仅划分 5 个核心大阶段:
序号 | 阶段名称 | 核心行为 | 通俗类比 |
1 | 实例化 | Spring 调用构造方法,新建空对象,属性未赋值 | 造出空水杯 |
2 | 属性赋值(依赖注入) | 自动装配 @Autowired、setter、构造依赖,填充对象字段 | 给水杯加水、茶叶 |
3 | 初始化 | 所有依赖注入完成,执行自定义初始化逻辑 | 烧水、调试水温 |
4 | 使用 | Bean 完全就绪,业务代码调用执行业务逻辑 | 喝水、正常使用 |
5 | 销毁 | IoC 容器关闭时,执行资源释放清理逻辑 | 倒掉水、清洗杯子收纳 |
表 2:完整细粒度标准执行流程(面试完整版)
简化 5 阶段内部包含 Spring 内置感知接口、三级初始化 / 销毁方法,完整执行顺序不可颠倒,全流程共 8 大细分步骤:
步骤 | 阶段细分 | 执行内容 | 关键接口 / 注解 |
1 | 实例化 Bean | 调用无参 / 有参构造器,创建原始对象 | 构造函数 |
2 | 属性填充 DI | 自动注入所有依赖、字段赋值 | @Autowired、setter 注入、构造注入 |
3 | Aware 接口回调 | Bean 获取 Spring 容器内部资源 | BeanNameAware、BeanFactoryAware、ApplicationContextAware |
4 | JSR250 初始化注解 | 依赖注入完成后执行初始化逻辑 | @PostConstruct |
5 | 初始化接口回调 | Spring 内置初始化标准接口 | InitializingBean#afterPropertiesSet() |
6 | 自定义 init 方法 | XML / @Bean 指定自定义初始化函数 | @Bean(initMethod = "xxx") |
7 | Bean 就绪使用 | 交给业务层调用,执行业务 | 业务自动注入使用 |
8 | 容器关闭销毁流程 | 容器 close () 时执行三级销毁逻辑 | @PreDestroy → DisposableBean → @Bean(destroyMethod) |
二、自定义初始化与销毁全方案对比
Spring 提供三套独立方式实现初始化、销毁逻辑,三套可同时共存,执行顺序固定,下面两张表格分别对比初始化、销毁方案。
表 3:三种初始化方式对比
实现方式 | 规范来源 | 执行优先级 | 优点 | 缺点 | 适用场景 |
@PostConstruct 注解 | JSR-250 Java 官方规范 | 1(最先执行) | 注解简洁、无框架侵入、推荐首选 | JDK9 + 需引入 jakarta 依赖 | 绝大多数项目初始化,加载配置、创建连接 |
InitializingBean 接口 | Spring 原生接口 | 2(中间执行) | 无需额外配置,容器自动识别 | 强耦合 Spring 框架 | 底层框架自定义 Bean 拓展 |
initMethod 自定义方法 | XML / @Bean 配置 | 3(最后执行) | 完全解耦框架,原有旧项目兼容 | 需要手动配置方法名,繁琐 | 第三方无源码类、老旧 XML 项目 |
表 4:三种销毁方式对比
实现方式 | 规范来源 | 执行优先级 | 生效前提 | 适用场景 |
@PreDestroy 注解 | JSR-250 规范 | 1(最先执行) | 仅单例 Bean 生效 | 日常业务释放线程池、数据库连接 |
DisposableBean 接口 | Spring 原生接口 | 2(中间执行) | 仅单例 Bean 生效 | 中间件底层资源回收 |
destroyMethod 自定义销毁 | XML/@Bean 配置 | 3(最后执行) | 仅单例 Bean 生效 | 第三方工具类关闭资源 |
补充核心规则
三套初始化同时存在:
@PostConstruct > InitializingBean > initMethod三套销毁同时存在:
@PreDestroy > DisposableBean > destroyMethod
三、Scope 作用域对生命周期的影响(核心难点)
Bean 的作用域直接决定实例创建时机、销毁逻辑是否触发,最常用 singleton(单例)、prototype(多例)差异巨大。
表 5:单例 vs 多例 Bean 生命周期差异
对比维度 | singleton 单例(默认) | prototype 多例 |
实例创建时机 | 容器启动时提前实例化(懒加载 lazy-init 除外) | 每次 @Autowired /getBean () 获取时才新建对象 |
实例数量 | 全局容器仅 1 个对象 | 每次获取全新独立对象 |
完整生命周期管控 | Spring 全程管理:实例化→注入→初始化→销毁 | Spring 只管理前 3 步(实例、注入、初始化) |
销毁方法触发 | 容器关闭时自动执行 @PreDestroy 等销毁逻辑 | 容器不管理销毁,销毁方法永远不会执行 |
资源风险 | 单例共享,注意线程安全 | 多对象频繁创建,容易内存溢出 |
适用场景 | 工具类、Service、Mapper、连接池 | 有状态对象(每次调用独立数据) |
四、完整代码演示(可直接运行)
import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; @Component public class LifeCycleDemo implements InitializingBean, DisposableBean { // 1.实例化:构造方法 public LifeCycleDemo() { System.out.println("步骤1:执行构造方法,实例化Bean"); } // 2.依赖注入,模拟属性赋值 public void setMsg(String msg) { System.out.println("步骤2:完成属性依赖注入赋值"); } // 方式1:JSR250初始化注解 优先级最高 @PostConstruct public void postConstructInit() { System.out.println("步骤4:@PostConstruct 初始化方法执行"); } // 方式2:Spring初始化接口 InitializingBean @Override public void afterPropertiesSet() throws Exception { System.out.println("步骤5:InitializingBean afterPropertiesSet 执行"); } // 方式3:自定义init方法,配合@Bean(initMethod)使用 public void customInit() { System.out.println("步骤6:自定义initMethod初始化方法"); } // 业务使用方法 public void serviceWork() { System.out.println("步骤7:Bean就绪,执行业务逻辑"); } // 方式1:JSR250销毁注解 优先级最高 @PreDestroy public void preDestroyClear() { System.out.println("销毁1:@PreDestroy 资源清理"); } // 方式2:Spring销毁接口 DisposableBean @Override public void destroy() throws Exception { System.out.println("销毁2:DisposableBean destroy 执行"); } // 方式3:自定义销毁方法,配合@Bean(destroyMethod) public void customDestroy() { System.out.println("销毁3:自定义destroyMethod执行"); } }五、高频业务使用场景汇总表
表 6:生命周期回调业务落地场景
回调类型 | 典型业务场景 |
@PostConstruct 初始化 | 项目启动加载本地配置文件、初始化 Redis 连接池、定时任务启动、缓存预热 |
@PreDestroy 销毁 | 服务停机关闭数据库连接、停止定时线程池、释放文件 IO 流、清空本地缓存 |
Aware 感知接口 | 项目中动态获取容器上下文、读取配置文件、发布容器事件 |
自定义 init/destroy | 第三方 SDK 初始化与关闭(无法修改源码) |
六、面试高频问答总结表
表 7:Bean 生命周期面试核心考点
面试问题 | 标准答案核心要点 |
Bean 完整生命周期顺序? | 实例化→DI 注入→Aware 回调→@PostConstruct→InitializingBean→initMethod→使用→容器关闭三级销毁 |
三种初始化执行顺序? | @PostConstruct > InitializingBean > initMethod |
prototype 多例会执行销毁方法吗? | 不会,Spring 不管理多例 Bean 销毁,@PreDestroy 无效 |
单例 Bean 何时创建? | 默认容器启动创建;加 @Lazy 懒加载,第一次使用才创建 |
InitializingBean 和 @PostConstruct 区别? | @PostConstruct 是 Java 规范无框架耦合;InitializingBean 是 Spring 原生接口,耦合框架 |
容器关闭如何触发销毁? | 调用容器 close ()、SpringBoot 服务正常停机,强制 kill 进程不会执行销毁方法 |
七、全文总结
1、基础简化生命周期分为实例化、属性赋值、初始化、使用、销毁5 大阶段,便于快速记忆;
2、底层完整流程包含 Aware 感知接口、三级初始化、三级销毁,执行顺序严格固定;
3、初始化 / 销毁各提供三种实现方案,开发优先推荐
@PostConstruct、@PreDestroy注解;4、Bean 作用域 Scope 是生命周期关键分水岭,单例完整管控销毁,多例无销毁逻辑;
5、生命周期回调核心价值:在 Bean 就绪 / 销毁节点自动管理资源,替代手动创建、释放连接,降低业务代码复杂度。
