深入理解 Spring Bean 生命周期的执行流程

server/2025/2/22 22:55:23/

在 Java 开发领域,Spring 框架无疑是一颗璀璨的明星,它极大地简化了企业级应用的开发过程。而 Spring Bean 的生命周期,作为 Spring 框架的核心概念之一,对于理解 Spring 框架的运行机制和进行高效开发至关重要。本文将详细剖析 Spring Bean 生命周期的执行流程,帮助大家更好地掌握这一关键知识点。

一、Spring Bean 生命周期概述

Spring Bean 的生命周期指的是一个 Bean 从创建到销毁所经历的一系列过程。理解这个过程,有助于我们在不同的阶段对 Bean 进行定制化处理,比如在 Bean 初始化时进行一些配置,或者在 Bean 销毁时释放资源。Spring Bean 的生命周期大致可以分为创建前准备阶段、创建实例阶段、依赖注入阶段、容器缓存阶段和销毁实例阶段。

二、创建前准备阶段

1. 配置解析

在 Bean 真正开始加载之前,Spring 会从上下文以及相关配置文件中解析并查找与 Bean 有关的扩展实现。其中,init - method 和 destroy - method 是两个重要的配置。init - method 用于指定容器在初始化 Bean 时要调用的方法,而 destroy - method 则用于指定容器在销毁 Bean 时要调用的方法。以下是一个在 XML 配置文件中使用这两个属性的示例:

收起

xml

<bean id="exampleBean" class="com.example.ExampleBean" init - method="init" destroy - method="destroy"/>

2. 扩展处理器调用

BeanFactoryPostProcessor 是 Spring 提供的一个强大的扩展机制。它允许在 Bean 定义被加载到 BeanFactory 之后,但在 Bean 实例化之前对 Bean 定义进行修改。在一些和 Spring 集成的中间件,如 Dubbo 中,就经常会使用 BeanFactoryPostProcessor 来动态修改 Bean 的定义,以满足特定的业务需求。

三、创建实例阶段

1. 反射创建实例

Spring 根据 Bean 的定义信息,使用 Java 的反射机制来创建 Bean 的实例。这就好比按照设计图纸搭建房子的框架。例如,当 Spring 解析到某个 Bean 的定义时,会调用其无参构造函数或者带参构造函数来创建实例。

2. 属性扫描与解析

在创建实例的同时,Spring 会扫描和解析 Bean 声明的一些属性。在 Java 类中,我们可以使用 @Value 注解来注入属性值,如下所示:

收起

java

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class ExampleBean {@Value("${example.property}")private String property;// 其他代码
}

四、依赖注入阶段

1. 依赖注入方式

如果被实例化的 Bean 依赖其他 Bean 对象,就需要进行依赖注入。常见的依赖注入方式有 @Autowired 注解注入和 setter 方法注入等。以下是一个使用 @Autowired 注解进行构造函数注入的示例:

收起

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class UserService {private UserRepository userRepository;@Autowiredpublic UserService(UserRepository userRepository) {this.userRepository = userRepository;}// 其他代码
}

2. 扩展接口调用

在这个阶段,会触发一些扩展接口的调用。

  • BeanPostProcessor:它有 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法,分别在 Bean 初始化前后调用。我们可以通过实现这个接口,在 Bean 的初始化前后进行额外的处理。
  • InitializingBean:实现该接口的 Bean 需要实现 afterPropertiesSet() 方法,此方法会在 Bean 的属性设置完成后调用。
  • BeanFactoryAware:实现该接口的 Bean 可以获取到 BeanFactory 实例,从而可以在 Bean 内部使用 BeanFactory 进行一些操作。

五、容器缓存阶段

1. 缓存保存

Spring 会将创建好并完成依赖注入的 Bean 保存到 singletonObjects 等缓存中,这样在后续需要使用该 Bean 时,可以直接从缓存中获取,提高了访问效率。

2. 初始化方法调用

如果在 Bean 定义时配置了 init - method 属性,该方法会在这个阶段被调用。以下是一个示例:

收起

java

public class ExampleBean {public void init() {// 初始化操作}// 其他代码
}

3. 后置处理器调用

BeanPostProcessor 的 postProcessAfterInitialization 方法也会在这个阶段触发,对 Bean 进行最后的处理。

六、销毁实例阶段

当 Spring 应用上下文关闭时,该上下文中的所有 Bean 都会被销毁。

1. 接口与属性调用

如果 Bean 实现了 DisposableBean 接口,其 destroy() 方法会被调用;或者如果在 Bean 定义时配置了 destroy - method 属性,对应的方法也会被调用。以下是一个实现 DisposableBean 接口的示例:

收起

java

import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;@Component
public class ExampleBean implements DisposableBean {@Overridepublic void destroy() throws Exception {// 销毁操作,如释放资源}// 其他代码
}

七、总结

Spring Bean 的生命周期是一个复杂而有序的过程,涵盖了从准备创建到最终销毁的各个阶段。每个阶段都有其特定的任务和扩展点,开发者可以利用这些扩展点来满足不同的业务需求。通过深入理解 Spring Bean 的生命周期,我们可以更好地掌握 Spring 框架的运行机制,编写出更加高效、灵活的代码。希望本文能帮助大家对 Spring Bean 的生命周期有更深入的认识。


http://www.ppmy.cn/server/169961.html

相关文章

利用分治策略优化快速排序

1. 基本思想 分治快速排序&#xff08;Quick Sort&#xff09;是一种基于分治法的排序算法&#xff0c;采用递归的方式将一个数组分割成小的子数组&#xff0c;并通过交换元素来使得每个子数组元素按照特定顺序排列&#xff0c;最终将整个数组排序。 快速排序的基本步骤&#…

微信小程序消息推送解密

package com.test.main.b2b;import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Arrays;/*** author * version 1.0* description: 解谜微信小…

基于Python+Django+Vue的旅游景区推荐系统系统设计与实现源代码+数据库+使用说明

运行截图 功能介绍 前台功能包括&#xff1a;首页、详情页、订单、用户中心。后台功能包括&#xff1a;首页、轮播图管理、管理员、卖家管理、买家管理、景区管理、订单管理非开源功能&#xff08;分类管理&#xff0c;地区管理&#xff0c;收藏管理&#xff0c;评论管理&a…

git使用-克隆远程项目、分支管理

文章目录 克隆远程项目到本地1. 远程找到需要克隆的项目&#xff0c;复制ssh地址2. idea开启git版本控制&#xff08;如果已经开了&#xff0c;忽略此步骤&#xff09;3. clone远端项目4. 克隆完成 分支管理1. 新建分支2. 切换分支3. 合并分支4. 储存变化 克隆远程项目到本地 …

win10把c盘docker虚拟硬盘映射迁移到别的磁盘

c盘空间本身就比较小、如果安装了docker服务后&#xff0c;安装的时候没选择其他硬盘&#xff0c;虚拟磁盘也在c盘会占用很大的空间&#xff0c;像我的就三十多个G&#xff0c;把它迁移到其他磁盘一下子节约几十G 1、先输入下面命令查看 docker 状态 wsl -l -v 2、如果没有停止…

【存储中间件API】MySQL、Redis、MongoDB、ES常见api操作及性能比较

常见中间件api操作及性能比较 ☝️ MySQL crud操作✌️ maven依赖✌️ 配置✌️ 定义实体类✌️ 常用api ☝️ Redis crud操作✌️ maven依赖✌️ 配置✌️ 常用api ☝️ MongoDB crud操作✌️ maven依赖✌️ 配置文件✌️ 定义实体类✌️ MongoDB常用api ☝️ ES crud操作 ⭐️…

Graspness Discovery in Clutters for Fast and Accurate Grasp Detection 解读

研究背景 研究问题 &#xff1a;这篇文章要解决的问题是如何在杂乱的环境中快速且准确地检测抓取姿态。传统的 6自由度抓取方法将场景中的所有点视为平等&#xff0c;并采用均匀采样来选择抓取候选点&#xff0c;但忽略了抓取位置的重要性&#xff0c;这极大地影响了抓取姿态检…

学习整理安装php的uuid扩展以及uuid调用方法

学习整理安装php的uuid扩展以及uuid调用方法 1、安装uuid依赖库2、下载并安装3、ini中添加扩展4、re2c版本报错5、uuid调用方法 1、安装uuid依赖库 yum -y install uuid uuid-devel e2fsprogs-devel libuuid-devel2、下载并安装 点我下载uuid安装包 wget http://pecl.php.ne…