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不是很熟,就根据网上的查到的知识和自己的摸索,将一…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
