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

深度解析 Spring Bean 生命周期

        在 Spring 框架的体系中,Bean 的生命周期管理是支撑应用稳定运行的核心逻辑。它精细把控着 Bean 从 “定义蓝图” 到 “销毁回收” 的每一步,深刻影响着依赖注入、AOP 增强、资源管理等关键功能。本文将结合实例化策略(构造函数、工厂方法)与属性注入(Setter 注入),完整拆解 Bean 生命周期的全流程,带你看透 Spring 容器的运作本质。

Bean 实例化的基本流程

  • 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的 BeanDefinition 对象;
  • 将 BeanDefinition 存储在一个名为 beanDefinitionMap 的Map<String,BeanDefinition>中;
  • ApplicationContext 底层遍历 beanDefinitionMap,创建 Bean 实例对象;
  • 创建好的 Bean 实例对象,被存储到一个名为singletonObjects的Map<String,Object>中;
  • 当执行 applicationContext.getBean(beanName) 时,从singletonObjects去匹配Bean实例返回

一、Bean 生命周期全景概览

Spring Bean 生命周期可拆解为 “定义→实例化→初始化→使用→销毁” 五大阶段,每个阶段又包含细分步骤,共同构建出 Bean 的完整生命周期:

二、阶段 1:BeanDefinition 加载(“定义蓝图”)

1. 核心逻辑

Spring 启动时,通过 BeanDefinitionReader(如 XML 解析器、注解扫描器 )解析配置(XML / 注解),将 Bean 的 “元数据”(类名、作用域、依赖、初始化方法等)转化为 BeanDefinition,存入 BeanDefinitionRegistry(容器的 “蓝图仓库” )。

2. 代码 / 配置示例

<!-- XML 配置定义 Bean -->
<bean id="userService" class="com.example.UserService"/>
// 注解扫描定义 Bean(@Service 会被转化为 BeanDefinition)
@Service
public class UserService {}

3. 作用

这一步是 “定义 Bean” 而非 “创建实例”,BeanDefinition 是后续实例化、注入的 “蓝图”,决定了 Bean 的基础配置。

三、阶段 2:实例化(构造 / 工厂方法创建对象)

实例化是 Bean 从 “蓝图” 到 “内存对象” 的第一步,Spring 提供 两种核心策略,按需选择创建方式:

策略 1:构造函数实例化(默认首选)

(1)核心逻辑
  • 无参构造:若 Bean 无特殊配置,Spring 默认调用 无参构造函数 创建实例。
  • 有参构造:若 Bean 定义了有参构造(或通过 @Autowired 标记),Spring 会自动解析参数依赖,从容器中查找匹配的 Bean 注入,再调用构造函数创建实例。
(2)代码示例
public class UserService {private UserDao userDao;// 有参构造 + 依赖注入(Spring 自动识别)@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;System.out.println("UserService 有参构造执行,注入 UserDao");}
}

如果不用注解的,对应的XML配置实现构造函数注入:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 1. 定义UserDao的Bean --><bean id="userDao" class="com.example.UserDao"/><!-- 2. 定义UserService的Bean,并通过构造函数注入UserDao --><bean id="userService" class="com.example.UserService"><!-- 通过constructor-arg指定构造函数参数,ref引用已定义的userDao Bean --><constructor-arg ref="userDao"/></bean></beans>
(3)使用场景

简单 Bean 创建、依赖需 “强制注入” 的场景(如 Service 依赖 Dao,构造时必须传入 )。                  

策略 2:工厂方法实例化(复杂场景适配)

(1)核心逻辑

通过 工厂类 / 工厂方法 创建 Bean,Spring 调用指定的工厂方法(静态 / 实例方法)生成实例,支持灵活的自定义逻辑。

(2)代码示例
// 工厂类
public class UserServiceFactory {private UserService service; // 通过setter 注入public void setUserService(UserService service) {this.service = service;}public UserService createUserService() {// 自定义初始化逻辑service.setMaxRetry(3); //将其 maxRetry(最大重试次数)属性设置为 3。return service;}
}
(3)适用场景

  • 第三方库对象创建(无法修改构造函数,需通过工厂封装 );
  • 复杂初始化逻辑(如设置默认参数、连接资源 )。

四、阶段 3:属性注入(Setter / 构造函数填充依赖)

实例化生成 “空对象” 后,Spring 会为 Bean 注入属性(依赖的其他 Bean、基本类型值 ),支持 两种核心方式

方式 1:Setter 注入(灵活可选)

(1)核心逻辑

通过 setXxx() 方法注入依赖,需配合 无参构造(或工厂方法创建实例后执行 ),适合 “可选依赖” 或 “需动态修改” 的场景。

(2)代码示例
public class UserService {private UserDao userDao;private int maxRetry;// 无参构造(实例化时执行)public UserService() {System.out.println("UserService 无参构造执行");}// Setter 注入 UserDao(依赖 Bean)@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;System.out.println("Setter 注入 UserDao");}// Setter 注入基本类型(maxRetry)public void setMaxRetry(int maxRetry) {this.maxRetry = maxRetry;System.out.println("Setter 注入 maxRetry:" + maxRetry);}
}
(3)适用场景
  • 依赖为 “可选”(如部分属性可后续动态设置 );
  • 兼容旧代码(无法修改构造函数,通过 Setter 注入适配 )。

方式 2:构造函数注入(强制依赖)

(1)核心逻辑

依赖通过 构造函数参数 注入(与 “构造函数实例化” 协同 ),适合 “强制依赖” 场景(依赖不注入则 Bean 无法工作 )。

(2)代码示例
public class UserService {private UserDao userDao;// 有参构造 + 依赖注入(强制传入 UserDao)public UserService(UserDao userDao) {this.userDao = userDao;System.out.println("构造函数注入 UserDao");}
}
(3)适用场景
  • 依赖为 “必须项”(如数据库连接,构造时必须初始化 );
  • 需避免 “依赖空指针” 的严格场景。

五、阶段 4:初始化(Aware、后置处理器、自定义逻辑)

实例化、注入完成后,Bean 进入 初始化阶段,执行一系列增强和自定义逻辑,包含 5 大关键步骤:

步骤 1:Aware 接口回调(感知容器)

(1)核心逻辑

若 Bean 实现 Aware 子接口(如 BeanNameAware、ApplicationContextAware ),Spring 会回调对应方法,让 Bean 主动获取容器信息(名称、上下文、工厂等 )。

(2)代码示例
public class UserService implements BeanNameAware {private String beanName;@Overridepublic void setBeanName(String name) {this.beanName = name;System.out.println("Aware 回调:Bean 名称为 " + name);}
}

步骤 2:BeanPostProcessor 前置处理(初始化前增强)

(1)核心逻辑

Spring 遍历所有 BeanPostProcessor(后置处理器 ),执行 postProcessBeforeInitialization,可在初始化前 增强 / 修改 Bean(如统一打日志、校验属性 )。

(2)代码示例
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {if (bean instanceof UserService) {System.out.println("初始化前增强:" + beanName);}return bean;}
}

步骤 3:InitializingBean 回调(afterPropertiesSet)

(1)核心逻辑

若 Bean 实现 InitializingBean 接口,Spring 调用 afterPropertiesSet 执行 自定义初始化逻辑(如依赖校验、资源初始化 )。

(2)代码示例
public class UserService implements InitializingBean {@Overridepublic void afterPropertiesSet() {System.out.println("InitializingBean 回调:执行自定义初始化");}
}

步骤 4:@PostConstruct 或 init-method(自定义初始化)

(1)核心逻辑

通过 @PostConstruct 注解或 XML 配置 init-method,执行 开发者自定义的初始化逻辑(如加载缓存、启动线程 )。

(2)代码示例
@Service
public class UserService {@PostConstructpublic void init() {System.out.println("@PostConstruct 执行:初始化缓存");}
}

步骤 5:BeanPostProcessor 后置处理(初始化后增强,如 AOP)

(1)核心逻辑

再次遍历 BeanPostProcessor,执行 postProcessAfterInitialization,最终增强 Bean(如 Spring AOP 在此生成代理对象,织入切面逻辑 )。

(2)典型场景

Spring AOP 的 AnnotationAwareAspectJAutoProxyCreator 在此步骤为 @Transactional 标注的 Bean 创建代理,实现事务功能。

六、阶段 5:使用(业务调用,Bean 投入运行)

初始化完成后,Bean 进入 “可用状态”,可通过以下方式被业务调用:

  • 依赖注入:其他 Bean 通过 @Autowired 注入使用;
  • 手动获取:通过 ApplicationContext.getBean("userService") 直接获取;
  • 事件驱动:作为监听器接收并处理容器事件。

七、阶段 6:销毁(容器关闭,资源回收)

容器关闭时,Spring 触发 销毁逻辑,释放 Bean 占用的资源(如数据库连接、线程池 ),支持以下方式:

方式 1:DisposableBean 回调(destroy 方法)

(1)核心逻辑

若 Bean 实现 DisposableBean 接口,Spring 调用 destroy 方法执行销毁。

(2)代码示例
public class UserService implements DisposableBean {@Overridepublic void destroy() {System.out.println("DisposableBean 回调:释放资源");}
}

方式 2:@PreDestroy 或 destroy-method(自定义销毁)

(1)核心逻辑

通过 @PreDestroy 注解或 XML 配置 destroy-method,执行 自定义销毁逻辑(如关闭连接、停止线程 )。

(2)代码示例
@Service
public class UserService {@PreDestroypublic void cleanUp() {System.out.println("@PreDestroy 执行:清理缓存");}
}

八、全流程总结:Bean 生命周期的 “建造者思维”

Spring Bean 生命周期是一场 “蓝图定义→实例创建→依赖注入→增强初始化→业务使用→销毁回收” 的完整流程,每个阶段都为 Bean 的 “可用” 与 “可控” 服务:

  1. BeanDefinition:定义 Bean 的 “蓝图”,决定基础配置;
  2. 实例化:通过构造 / 工厂方法将 “蓝图” 转化为 “内存对象”;
  3. 属性注入:填充依赖,让 Bean 具备 “协作能力”;
  4. 初始化:通过 Aware、后置处理器、自定义逻辑,让 Bean 具备 “业务能力”;
  5. 使用:Bean 投入业务,支撑应用运行;
  6. 销毁:容器关闭时回收资源,保证应用 “优雅退出”。

理解这一流程,不仅能让你精准把控 Bean 的创建与管理,更能在复杂场景中(如 AOP 失效排查、自定义 Bean 增强 )快速定位问题,让 Spring 框架成为你构建稳健应用的 “得力助手”。

http://www.lryc.cn/news/623760.html

相关文章:

  • Microsoft WebView2
  • SQL详细语法教程(四)约束和多表查询
  • 网络常识-我的电脑啥时安装了证书
  • 【力扣热题100】双指针—— 接雨水
  • 【AI智能体】Dify 搭建发票识别助手操作实战详解
  • 微信小程序 小白gps工具v0.01 使用说明
  • XF 306-2025 阻燃耐火电线电缆检测
  • QUIC浅析
  • C++ 标准模板库 (^^ゞ 致敬 STL 创始人 Alexander Stepanov
  • 笔记本电脑wifi小图标不见了 或者 蓝牙功能消失、电脑开不开机解决方法
  • 基于飞算JavaAI的可视化数据分析集成系统项目实践:从需求到落地的全流程解析
  • Shell脚本-while循环语法结构
  • ACPI TABLE 方式加载device driver--以spi controller为例
  • 字节 Golang 大模型应用开发框架 Eino简介
  • Pulsar存储计算分离架构设计之存储层BookKeeper(上)
  • 在线编程题目之小试牛刀
  • C#高级语法_委托
  • Windows平台Frida逆向分析环境完整搭建指南
  • 从需求到部署全套方案:餐饮服务许可证数据可视化分析系统的大数据技术实战
  • 发票识别工具,合并PDF提取信息
  • JavaScript字符串详解
  • 001.Redis 简介及安装
  • 【杂谈】-以质代量:谷歌主动学习范式重构AI训练逻辑
  • Mac(四)自定义按键工具 Hammerspoon 的安装和使用
  • vue封装请求拦截器 响应拦截器
  • SCAI采用公平发射机制成功登陆LetsBonk,60%代币供应量已锁仓
  • 智能合约里的 “拒绝服务“ 攻击:让你的合约变成 “死机的手机“
  • 数学建模 14 中心对数比变换
  • 原子操作及基于原子操作的shared_ptr实现
  • Leaflet赋能:WebGIS视角下的省域区县天气可视化实战攻略