Spring 怎么解决循环依赖的问题?

Spring框架解决循环依赖主要通过三级缓存来实现,这主要发生在Spring容器创建bean的过程中。以下是Spring解决循环依赖的基本步骤:

  1. 一级缓存(singletonObjects):存放已经创建好的单例对象,供其他bean引用。

  2. 二级缓存(earlySingletonObjects):存放原始的bean对象,即已经填充了属性(依赖注入完成)但尚未经过初始化(调用afterPropertiesSet方法)的bean对象。

  3. 三级缓存(singletonFactories):存放bean工厂对象(BeanFactoryObjectProvider),用于解决循环依赖。当Spring容器创建bean时,如果检测到循环依赖,它会将bean的早期引用(early reference)存入三级缓存中。

具体步骤如下:

  • 创建Bean:当Spring容器创建一个bean时,首先会检查该bean是否已经存在于一级缓存中。如果存在,则直接使用;如果不存在,则继续创建。

  • 注册Bean:在bean创建过程中,Spring会将bean的早期引用(未初始化的bean对象)注册到二级缓存中。

  • 处理循环依赖:如果bean A依赖于bean B,而bean B又依赖于bean A,当Spring容器创建bean A时,会尝试创建bean B。此时,如果bean B尚未完全创建,Spring容器会从二级缓存中获取bean B的早期引用,并将其注入到bean A中。

  • 使用三级缓存:在bean B的创建过程中,如果检测到对bean A的依赖,Spring容器会从三级缓存中获取bean A的早期引用,并将其注入到bean B中。这样,即使bean A尚未完全创建,bean B也可以继续创建。

  • 初始化Bean:当所有依赖都注入完成后,Spring容器会调用bean的afterPropertiesSet方法进行初始化,并将bean从二级缓存移动到一级缓存中。

  • 完成创建:此时,bean A和bean B都已完成创建,并且相互引用,循环依赖问题得到解决。

需要注意的是,Spring只能解决单例作用域的bean的循环依赖问题,对于原型作用域的bean,Spring无法处理循环依赖。

下面V哥将通过一个简单的示例来解释Spring如何解决循环依赖的问题,并结合一个业务场景进行说明。

假设我们有一个电商系统,其中有两个组件:OrderService(订单服务)和PaymentService(支付服务)。这两个服务相互依赖:OrderService需要使用PaymentService来处理支付,而PaymentService又需要OrderService来确认订单状态。

首先,我们定义这两个服务的接口和实现类。

OrderService.java

public class OrderService {private PaymentService paymentService;public void setPaymentService(PaymentService paymentService) {this.paymentService = paymentService;}public void createOrder() {// 创建订单逻辑paymentService.processPayment();}
}

PaymentService.java

public class PaymentService {private OrderService orderService;public void setOrderService(OrderService orderService) {this.orderService = orderService;}public void processPayment() {// 处理支付逻辑orderService.confirmOrderStatus();}
}

在这两个类中,OrderService通过setter方法注入了PaymentService,而PaymentService也通过setter方法注入了OrderService,这就形成了一个循环依赖。

接下来,我们配置Spring容器,将这两个bean定义为单例(singleton)作用域。

applicationContext.xml

<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"><bean id="orderService" class="com.example.OrderService" scope="singleton"/><bean id="paymentService" class="com.example.PaymentService" scope="singleton"/>
</beans>

现在,当Spring容器启动时,它会创建这两个bean。由于它们之间存在循环依赖,Spring将使用三级缓存来解决这个问题:

  • 创建OrderService Bean:Spring首先尝试创建OrderService bean,并将其注册到二级缓存中。

  • 注入PaymentService:在创建OrderService的过程中,Spring需要注入PaymentService。由于PaymentService尚未完全创建,Spring会尝试从二级缓存中获取PaymentService的早期引用。

  • 创建PaymentService Bean:此时,Spring开始创建PaymentService bean,并将其注册到二级缓存中。

  • 注入OrderService:在创建PaymentService的过程中,Spring需要注入OrderService。由于OrderService已经在二级缓存中,Spring会将其早期引用注入到PaymentService中。

  • 完成初始化:一旦所有依赖都注入完成,Spring会调用每个bean的afterPropertiesSet方法(如果有的话),然后将它们从二级缓存移动到一级缓存中。

  • 解决循环依赖:由于Spring使用了三级缓存来存储bean的早期引用,即使在bean完全创建之前,也可以将它们注入到其他bean中,从而解决了循环依赖问题。

通过这个示例,我们可以看到Spring如何解决循环依赖的问题,并确保了OrderService和PaymentService可以正常工作,即使它们之间存在相互依赖的关系。这种机制使得Spring容器可以灵活地处理复杂的依赖关系,而不需要开发者手动干预。

通过这种方式,Spring框架有效地解决了单例bean的循环依赖问题,确保了依赖注入的顺利进行。关注【威哥爱编程】一起卷起来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/25258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

语法分析!!!

一、实验题目 根据给定文法编写调试预测分析程序&#xff0c;对任意输入串用预测分析法进行语法分析。 二、实验目的 加深对预测分析法的理解。 三、实验内容 四、实验代码 #include <iostream> #include <stdio.h> #include <string> #include <…

隐式链接DLL

本文仅供学习交流&#xff0c;严禁用于商业用途&#xff0c;如本文涉及侵权请及时联系本人将于及时删除 【例9.5】创建的基于MFC对话框的应用程序MFCImLink2&#xff0c;隐式链接例9.2创建的MFCLibrary2.dll&#xff0c;使用其中的导出函数求正方形的面积。 (1) 使用MFC应用程…

【零基础一看就会】Python爬虫从入门到应用(下)

目录 一、urllib的学习 1.1 urllib介绍 1.2 urllib的基本方法介绍 urllib.Request &#xff08;1&#xff09;构造简单请求 &#xff08;2&#xff09;传入headers参数 &#xff08;3&#xff09;传入data参数 实现发送post请求&#xff08;示例&#xff09; response.…

野火FPGA跟练(四)——串口RS232、亚稳态

目录 简介接口与引脚通信协议亚稳态RS232接收模块模块框图时序波形RTL 代码易错点Testbench 代码仿真 RS232发送模块模块框图时序波形RTL 代码Testbench 代码仿真 简介 UART&#xff1a;Universal Asynchronous Receiver/Transmitter&#xff0c;异步串行通信接口。发送数据时…

网络流媒体协议——RTMP

流媒体协议常用实时信息传输协议(Real-Time Messaging Protocol,RTMP)和 HLS 协议。RTMP 为应用层协议,由 TCP 提供传输层的连接和传输服务,默认端口为1935。 RTMP URL rtmp://host:port/app/steamrtmp∶ 表示该URL必须以RTMP进行解析。host, port 分别表示主机地址和端口…

微服务开发与实战Day04

一、网关路由 网关&#xff1a;就是网络的关口&#xff0c;负责请求的路由、转发、身份校验。 在SpringCloud中网关的实现包括两种&#xff1a; 1. 快速入门 Spring Cloud Gateway 步骤&#xff1a; ①新建hm-gateway模块 ②引入依赖pom.xml(hm-gateway) <?xml version…

解锁俄罗斯市场:如何选择优质的俄罗斯云服务器

在当前云计算市场上&#xff0c;很多大型的云厂商并没有俄罗斯服务器的云节点&#xff0c;这给许多企业在拓展海外业务时带来了一定的困扰。然而&#xff0c;俄罗斯作为一个经济发展迅速的国家&#xff0c;其市场潜力不可忽视。因此&#xff0c;选择一台优质的俄罗斯云服务器成…

【MySQL】(基础篇三) —— 创建数据库和表

管理数据库和表 管理数据库 创建数据库 在MySQL中&#xff0c;创建数据库的SQL命令相对简单&#xff0c;基本语法如下&#xff1a; CREATE DATABASE 数据库名;如果你想避免在尝试创建已经存在的数据库时出现错误&#xff0c;可以添加 IF NOT EXISTS 子句&#xff0c;这样如…

04-4.1.2 串的存储结构

&#x1f44b; Hi, I’m Beast Cheng&#x1f440; I’m interested in photography, hiking, landscape…&#x1f331; I’m currently learning python, javascript, kotlin…&#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以订…

数据结构(C):二叉树前中后序和层序详解及代码实现及深度刨析

目录 &#x1f31e;0.前言 &#x1f688;1.二叉树链式结构的代码是实现 &#x1f688;2.二叉树的遍历及代码实现和深度刨析代码 &#x1f69d;2.1前序遍历 ✈️2.1.1前序遍历的理解 ✈️2.1.2前序代码的实现 ✈️2.1.3前序代码的深度解剖 &#x1f69d;2.2中序遍历 ✈…

Spring boot SSL证书路径配置

SSL证书路径配置: 1、打包到resouce下&#xff1a; server:port: 443ssl:enabled: truekey-store: classpath:XX.XX.com.p12key-store-password: your-passwordkeyStoreType: PKCS12keyAlias: your-alias 2、放到windows类型服务器硬盘上 Windows系统中&#xff0c;由于路径…

一些常用的frida脚本

这里整理一些常用的frida脚本&#xff0c;和ghidra 一起食用风味更佳&#xff5e; Trace RegisterNatives 注意到从java到c的绑定中&#xff0c;可能会在JNI_OnLoad动态的执行RegisterNatives方法来绑定java层的函数到c行数&#xff0c;可以通过这个方法&#xff0c;来吧运行…

VSCode 1.90版本 升级需谨慎~(Python)

由于再次出现justMyCode的问题&#xff0c;请使用Python的小伙伴要谨慎将Visual Studio Code升级到1.90版本&#xff08;两天前官方刚发布的&#xff09; 若已经升级到1.90的小伙伴&#xff0c;可以从这里下载1.89版本进行“补救“&#xff1a; 1.89.1版本下载链接&#xff1a;…

Android 14.0 修改wifi信号强度和信号等级

1.前言 在14.0的系统rom产品定制化开发中,在进行产品开发中,对应系统定制会有各种各样的需求,对纯wifi产品而言,对于wifi要求也是越来越高,因此有客户要求对wifi信号强度做定制,修改信号强度来增强显示wifi信号,所以要对wifi显示信号强度的相关代码做修改 2.修改wifi信…

计算机网络:数据链路层 - 扩展的以太网

计算机网络&#xff1a;数据链路层 - 扩展的以太网 集线器交换机自学习算法单点故障 集线器 这是以前常见的总线型以太网&#xff0c;他最初使用粗铜轴电缆作为传输媒体&#xff0c;后来演进到使用价格相对便宜的细铜轴电缆。 后来&#xff0c;以太网发展出来了一种使用大规模…

AI菜鸟向前飞 — LangChain系列之十七 - 剖析AgentExecutor

AgentExecutor 顾名思义&#xff0c;Agent执行器&#xff0c;本篇先简单看看LangChain是如何实现的。 先回顾 AI菜鸟向前飞 — LangChain系列之十四 - Agent系列&#xff1a;从现象看机制&#xff08;上篇&#xff09; AI菜鸟向前飞 — LangChain系列之十五 - Agent系列&#…

Springboot使用webupload大文件分片上传(包含前后端源码)

Springboot使用webupload大文件分片上传&#xff08;包含源码&#xff09; 1. 实现效果1.1 分片上传效果图1.2 分片上传技术介绍 2. 分片上传前端实现2.1 什么是WebUploader&#xff1f;功能特点接口说明事件APIHook 机制 2.2 前端代码实现2.2.1&#xff08;不推荐&#xff09;…

词向量对模型performance的影响

因为自己搭建了一个4层的transformer网络&#xff0c;然后词向量的维度是96(attention is all you need里面transformer block的dim512)&#xff0c;这里设置96是为了后续我需要做一些attack的任务。 然后使用transformer4对YELP(5分类)分类的时候&#xff0c;performance一直…

【深度学习基础】池化层

池化层&#xff08;Pooling Layer&#xff09;在卷积神经网络&#xff08;CNN&#xff09;中常用于计算机视觉任务&#xff0c;但在自然语言处理&#xff08;NLP&#xff09;任务中也有广泛的应用。池化层在NLP任务中可以帮助提取重要特征&#xff0c;降低数据维度&#xff0c;…

计算机组成原理之计算机系统层次结构

目录 计算机系统层次结构 复习提示 1.计算机系统的组成 2.计算机硬件 2.1冯诺依曼机基本思想 2.1.1冯诺依曼计算机的特点 2.2计算机的功能部件 2.2.1MAR 和 MDR 位数的概念和计算 3.计算机软件 3.1系统软件和应用软件 3.2三个级别的语言 3.2.1三种机器语言的特点 3…