Spring系列:Spring如何解决循环依赖
❤ 作者主页:欢迎来到我的技术博客😎
❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~*
🍊 如果文章对您有帮助,记得关注、点赞、收藏、评论⭐️⭐️⭐️
📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉
文章目录
- 1、什么是循环依赖
- 2、Spring实例Bean的本质
- 3、Spring可以解决哪些情况下的循环依赖
- 4、Spring怎么解决循环依赖
- 5、为什么解决Spring循环依赖需要三级缓存,而二级缓存却不行
- 6、总结
1、什么是循环依赖
在Spring框架中,循环依赖指的是两个或多个Bean之间相互依赖的情况,形成了依赖环路(Circular Dependency)。换句话说,这些Bean之间存在着相互引用,导致无法正确地创建和初始化这些 Bean。
通俗来讲,就是 Bean A 依赖 Bean B,而 Bean B 又依赖于 Bean A,或者是 Bean C 依赖自己本身,如下图所示:
2、Spring实例Bean的本质
在Spring中,当实例化一个Bean时,会按照依赖关系递归地实例化其所依赖的所有Bean,直到某个Bean不再依赖其他Bean或其依赖已经被实例化过。
具体来说,当实例化 Bean A 时,如果 Bean A 有依赖另一个 Bean B,Spring会先实例化 Bean B,并将其注入到 Bean A 中。而如果 Bean B 又依赖其他 Bean C,那么Spring会先实例化 Bean C,并将其注入到 Bean B 中,以此类推,直到找到一个 Bean 没有依赖其他Bean为止。
3、Spring可以解决哪些情况下的循环依赖
Spring解决循环依赖是由前置条件的:
- 出现循环依赖的Bean必须要是单例(singleton),如果依赖prototype则完全不会有此需求
- 依赖注入的方式不能全是构造器注入的方式
依赖情况 | 依赖注入方式 | 是否解决 |
---|---|---|
AB循环依赖 | AB均采用构造器注入 | 否 |
AB循环依赖 | AB均采用setter方式注入 | 是 |
AB循环依赖 | AB均采用属性自动注入 | 是 |
AB循环依赖 | A中注入的B为setter注入,B中注入的A为构造器注入 | 是 |
AB循环依赖 | B中注入的A为setter注入,A中注入的B为构造器注入 | 否 |
注意: 第四种可以而第五种不可以的原因是 Spring 在创建 Bean 时默认会根据自然排序进行创建,所以 A 会先于 B 进行创建。
4、Spring怎么解决循环依赖
Spring通过 三级缓存 解决循环依赖:
- 一级缓存
Map<String,Object> singletonObjects
:存放完全初始化好的Bean集合 - 二级缓存
Map<String,Object> earlySingletonObjects
:存放创建好但没有初始化属性的Bean集合 - 三级缓存
Map<String,ObjectFactory<?>> singletonFactories
:存放正在被创建的Bean的集合
当A、B两个类发生循环依赖时,我们看一下Spring是怎么解决循环依赖的:
- 创建A实例,实例化的时候把A对象工厂放入三级缓存,表示A开始实例化了,虽然这个对象还不完整,但是先曝出来让大家知道
- A注入属性时,发现依赖于B,此时B还没有创建出来,所以先去实例化B。
- 同样的,B在注入属性时发现依赖于A,它就会从缓存里找A对象。以此从一级缓存到三级缓存去查询A,从三级缓存通过对象工厂拿到A,发现A虽然不太完善,但是却存在,于是把A放入二级缓存,同时删除三级缓存中的A。此时,B已经实例化并且初始化完成,把B放入到一级缓存
4. 接着A继续属性赋值,顺利从一级缓存中拿到实例化且初始化完成的B对象。此时,A对象也创建完成,删除二级缓存中的A,同时把A放入到一级缓存
5. 最后,一级缓存中保存实例化、初始化完成的A、B对象,Spring也顺利解决了循环依赖的问题。
注意:
因此,我们就知道为什么Spring能解决setter注入的循环依赖了,因为实例化和属性赋值是分开的,所以里面有操作的空间。如果都是构造器注入的话,那么都得在实例化这一步完成注入,所以自然是无法支持了。
5、为什么解决Spring循环依赖需要三级缓存,而二级缓存却不行
Spring框架解决循环依赖的过程中确实使用了三级缓存。这是因为在单纯的二级缓存情况下,可能会出现无法解决的循环依赖问题。
二级缓存仅仅可以解决同一个Bean在同一个解析过程中的循环依赖,但如果存在多个解析过程,二级缓存就无法满足需求。所以,Spring引入了三级缓存,以便更好地管理和解决多个Bean之间的循环依赖问题。
三级缓存的引入使得Spring可以在不同解析阶段间共享缓存,有效地解决了复杂的循环依赖情况,确保了Bean的正确初始化。
6、总结
- 处理循环依赖有多种方式。首先考虑是否能够通过重新设计依赖来避免循环依赖。
- 如果确实不可避免需要循环依赖,那么通过上面提到的方式来处理。优先建议使用setter注入来解决。
非常感谢您阅读到这里,如果这篇文章对您有帮助,希望能留下您的点赞👍 关注💖 分享👥 留言💬thanks!!!
相关文章:

Spring系列:Spring如何解决循环依赖
❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得关注、点赞、收藏、…...

netty源码:(40)ReplayingDecoder
ReplayingDecoder是ByteToMessageDecoder的子类,我们继承这个类时,也要实现decode方法,示例如下: package cn.edu.tju;import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handle…...

Apache Doris (五十五): Doris Join类型 - Colocation Join
🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. Colocation Join原理...

计算机组成原理复习7
内存管理 文章目录 内存管理存储器概述存储器的分类按在计算机中的作用(层次)分类按存储介质分类按存取方式分类按信息的可保存性分类 存储器的性能指标存储容量单位成本存储速度:数据传输率数据的宽度/存储周期 存储器的层次化结构多级存储系…...

python使用openpyxl操作excel
文章目录 前提读取已有excel创建一个excel工作簿对象创建excel工作簿中的工作表获取工作表第一种:.active 方法第二种:通过工作表名获取指定工作表第三种:.get_sheet_name() 修改工作表的名称数据操作写入数据按单元格写入通过指…...

使用keepalived时虚拟IP漂移注意事项
什么是Keepalived服务 keepalived是一个开源的软件项目,用于实现高可用性(HA)的网络服务器负载均衡和故障转移。它允许将多台服务器组合在一起,形成一个虚拟服务器集群,实现负载均衡和故障转移。 keepalived的核心功…...

32阵元 MVDR和DREC DOA估计波束方向图对比
32阵元 MVDR和DREC DOA估计波束方向图对比 一、原理 MVDR原理:https://zhuanlan.zhihu.com/p/457528114 DREC原理(无失真响应特征干扰相消器):http://radarst.ijournal.cn/html/2019/3/201903018.html 主要参数: 阵…...

OpenCV-11颜色通道的分离与合并
本次我们使用两个比较重要的API split(mat)将图像的通道进行分割。 merge((ch1,ch2,ch3))将多个通道进行融合。 示例代码如下: import cv2 import numpy as npimg np.zeros((480, 640, 3),…...

从0到1入门C++编程——01 C++基础知识
文章目录 一、工具安装二、新建项目三、设置字体、注释、行号四、C基础知识1.数据类型2.输入输出3.运算符4.选择、循环结构5.跳转语句6.数组7.函数8.指针9.结构体 一、工具安装 学习C使用到的工具是Visual Studio,Visual Studio 2010旗舰版下载链接:点此…...

C#编程-编写和执行C#程序2
C#编程-编写和执行C#程序 问题陈述 Dvid所在的团队正在为网球比赛开发自动排名软件。他负责创建一个程序来接受网球选手的以下详细信息并将其显示在屏幕上: 1.姓名 2.排名 您需要帮助David创建该程序。 要创建所需的程序,David需要执行以下步骤: 1.打开“记事本”。 2.在“…...
Day02-ES6
一.proxy代理 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head>…...
2023年12月记录内容管理
文章目录 前言1.[vue构建项目](https://mp.csdn.net/mp_blog/creation/editor/134829688)2. [Nodejs后端express框架](https://mp.csdn.net/mp_blog/creation/editor/134841711)3. [前端知识点](https://mp.csdn.net/mp_blog/creation/editor/132810879)4.[前端知识点-vue篇&am…...

【测试基础】构造测试数据之 MySQL 篇
构造测试数据之 MySQL 篇 作为一名测试工程师,我们经常会构造测试数据进行一些功能验证。为了暴露更多的问题,在测试数据的构造上,我们应该尽可能的构造不同类型字段的数据,且一张表的字段最好不低于 10 10 10 个。 对于 MySQL …...

基于单片机的语音识别自动避障小车(论文+源码)
1.系统设计 此次基于单片机的语音识别自动避障小车,以STC89C52单片机作为系统的主控制器,利用超声波模块来实现小车与障碍物距离的测量并通过LCD液晶显示,当距离低于阈值时会通过WT588语音模块进行报警提示,并且小车会后退来躲避…...

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项样题卷①
2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项(高职组) 样题(第1套) 目录 2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项(高职组) 样题(第1套) 模块一…...

【信息安全原理】——入侵检测与网络欺骗(学习笔记)
📖 前言:在网络安全防护领域,防火墙是保护网络安全的一种最常用的设备。网络管理员希望通过在网络边界合理使用防火墙,屏蔽源于外网的各类网络攻击。但是,防火墙由于自身的种种限制,并不能阻止所有攻击行为…...

JVM GC 算法原理概述
对于JVM的垃圾收集(GC),这是一个作为Java开发者必须了解的内容,那么,我们需要去了解哪些内容呢,其实,GC主要是解决下面的三个问题: 哪些内存需要回收? 什么时候回收&…...
【数值分析】LU分解解Ax=b,matlab自己编程实现
LU分解(直接三角分解,Doolittle分解) A x b , A L U Axb \,\,,\,\, ALU Axb,ALU { L y b U x y \begin{cases} Lyb \\ Uxy \end{cases} {LybUxy 矩阵 L {L} L 的对角元素为 1 {1} 1 ,矩阵 U {U} U 的第一行和 A {A} A …...

华为HCIE-Datacom课程介绍
厦门微思网络HCIE-Datacom课程介绍 一、认证简介 HCIE-Datacom(Huawei Certified ICT Expert-Datacom)认证是华为认证体系中的顶级认证,HCIE-Datacom认证定位具备坚实的企业网络跨场景融合解决方案理论知识,能够使用华为数通产品…...
QT(C++)-QTableWight添加行和删除空行
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、QTableWidget的添加行3、删除行 1、前言 最近要用QT开发项目,对QT不是很熟,就根据网上的查到的知识和自己的摸索,将一…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...