【Spring】Spring循环依赖的处理

循环依赖是指两个或多个组件之间相互依赖,形成一个闭环,从而导致这些组件无法正确地被初始化或加载。这种情况可能会在软件开发中引起问题,因为循环依赖会导致初始化顺序混乱,组件之间的关系变得复杂,甚至可能引发死锁或其他不稳定行为。

在编程中,循环依赖通常出现在模块、类、或者组件之间的相互引用上,导致编译、加载或初始化过程中的问题。在依赖注入(DI)框架中,循环依赖可能会导致对象的创建和初始化失败。

@Service
public class TestService1 {@Autowiredprivate TestService2 testService2;public void test1() {}
}@Service
public class TestService2 {@Autowiredprivate TestService1 testService1;public void test2() {}
}

A 依赖于 B,而 B 也依赖于 A,形成了循环依赖。如果没有适当的处理,初始化这两个类的实例可能会导致问题。这段代码之所以能正常运行,是因为Spring内部机制,解决了循环依赖的问题。

Spring内部有三级缓存

  • singletonObjects 一级缓存,用于保存实例化、注入、初始化完成的bean实例
  • earlySingletonObjects 二级缓存,用于保存实例化完成的bean实例
  • singletonFactories 三级缓存,用于保存bean创建工厂,以便于后面扩展有机会创建代理对象。

Spring解决循环依赖步骤:

  1. Bean 的注册:首先,Spring会解析并注册所有的Bean定义,但不会立即创建Bean的实例。

  2. 提前创建 Bean 实例:对于每个要创建的单例(@Service默认是单例作用域),Spring会提前创建一个半初始化的实例,并将其放入singletonFactories缓存中。这是为了解决循环依赖问题。

  3. 开始创建 TestService1:当开始创建TestService1时,发现它依赖于TestService2。因为TestService2的半初始化实例已经在singletonFactories缓存中,所以会使用该实例创建TestService1,并在singletonFactories缓存中移除TestService2的工厂。

  4. 开始创建 TestService2:当创建TestService2时,发现它依赖于TestService1,但由于TestService1的半初始化实例已经存在,所以会使用该实例创建TestService2,并在singletonFactories缓存中移除TestService1的工厂。

  5. 完全初始化:一旦创建过程完成,Spring会执行TestService1TestService2的初始化操作,包括注入和其他初始化方法。这将使它们变成完全初始化的Bean

图解:

循环依赖可能出现的场景

  1. 模块之间的相互引用:在模块化的软件设计中,不同模块之间可能会相互引用,特别是当模块之间存在交叉的功能需求或依赖时。如果模块之间的依赖关系没有正确管理,就可能产生循环依赖。

  2. 类的相互引用:在面向对象编程中,不同类之间可能会有相互引用,尤其是在它们之间存在双向的依赖关系时。如果类的构造函数或方法参数中出现了相互引用,就可能导致循环依赖问题。

  3. 依赖注入框架配置不当:依赖注入框架(如Spring)用于管理组件之间的依赖关系。如果配置文件中出现了循环依赖,框架可能无法正确初始化对象,导致异常。

  4. 事件和消息驱动的系统:在事件和消息驱动的系统中,不同组件可能通过事件或消息进行通信。如果事件的发起者和接收者之间出现相互依赖,就可能导致循环依赖。

  5. 单例模式的使用:当使用单例模式时,如果多个单例对象之间相互依赖,可能会形成循环依赖。单例对象在整个应用程序中只有一个实例,因此其依赖关系需要特别注意。

  6. 构建和初始化顺序问题:在某些情况下,对象的构建和初始化顺序可能导致循环依赖。如果某个对象在构建阶段需要引用另一个对象,而后者又需要在构建阶段引用前者,就可能形成循环依赖。

如何解决循环依赖

  1. 重构设计:重新审视组件之间的关系,尝试将循环依赖问题转化为单向的依赖关系。这可能需要重新划分模块或类的职责,以减少相互依赖。

  2. 引入接口或抽象类:通过引入接口或抽象类,可以将具体的依赖关系替换为更高层次的抽象依赖,从而解耦循环依赖。

  3. 延迟初始化:将对象的初始化推迟到实际使用它们的时候,以避免在初始化阶段出现循环依赖。这可以通过懒加载等方式来实现。

  4. 使用中介者模式:引入中介者或事件系统,将类之间的通信转移到中介者中,从而降低直接的循环依赖。这可以将相互依赖的关系集中在一个地方进行处理。

  5. 使用依赖注入容器:依赖注入框架(如Spring)可以处理循环依赖问题。这些框架使用一些特殊的策略,以确保对象的正确初始化顺序,从而解决循环依赖。

  6. 通过Setter注入或后处理器解决:在某些情况下,通过使用Setter方法注入依赖或使用依赖后处理器可以解决循环依赖问题。这样,对象的构建和初始化可以分为多个步骤。

  7. 更改对象创建时机:有时,将对象的创建从构造函数移至其他方法中,可以避免在构造函数阶段引发循环依赖。

  8. 设计模式:一些设计模式,如工厂方法模式、抽象工厂模式,可以用来分离对象的构建和初始化,从而避免循环依赖。

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

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

相关文章

【前车之鉴】: 2023最新教程-将java程序打包到maven私服的正确打开方式,详细流程介绍不怕你掌握不了

文章目录 为什么看这篇整体流程1. 注册账号【首次需要】2. 工单申请【新项目必须】3. 项目配置【新项目必须】4. 授权认证【新项目必须】5. 一键发布 最后也很重要 为什么看这篇 一是当前网络上一些博客有遗漏部分,这里做补充,二是网上思路没错&#xff…

_数字矩阵

题目&#xff1a;一个3阶的数字矩阵如下&#xff1a; 1 2 3 8 9 4 7 6 5 现在给定数字n(1<n≤20)&#xff0c;输出n阶数字矩阵。 思路&#xff1a; 放出一条好玩的贪吃蛇&#xff0c;按照右下左上的顺序吃蛋糕&#xff0c;一边吃蛋糕&#xff0c;一边拉数字&#xff1b…

使用 PowerShell 下载文件

使用 PowerShell 下载文件 Invoke-WebRequest例子优点缺点 System.Net.WebClient例子优点缺点 Start-BitsTransfer例子优点缺点 Invoke-WebRequest 例子 Invoke-WebRequest -Uri "http://xxxx/test.txt" -OutFile "D:/test.txt"优点 容易上手&#xff0…

vue h5项目 打包加载优化

打包美化: 1&#xff09;npx browserslistlatest --update-db 更新去除警告 2&#xff09;打包进度条 npm add progress-bar-webpack-plugin -D npm add webpackbar -D npm install --save-dev webpack-bundle-analyzer 优化&#xff1a; 1.各个插件和loader所花费的时间 …

编写Dockerfile制作Web应用系统nginx镜像

文章目录 题目要求&#xff1a;一、创建文档&#xff0c;编写Dockerfile文件可以将harbor仓库去启动先起来 二、运行Dockerfile&#xff0c;构建nginx镜像三、推送导私有仓库&#xff0c;也就是我们的harbor仓库 题目要求&#xff1a; 编写Dockerfile制作Web应用系统nginx镜像…

fastadmin iis伪静态应用入口文件index.php

<?xml version"1.0" encoding"UTF-8"?> <configuration><system.webServer><rewrite><rules><rule name"OrgPage" stopProcessing"true"><match url"^(.*)$" /><conditions…

【Interaction交互模块】AngularJointDrive角度关节驱动

文章目录 一、预设体位置二、案例&#xff1a;做一个“能开合的门” 1、在已建好的门框下&#xff0c;建门 2、设置参数 3、解决产生的问题 一、预设体位置 交互模块——可控制物体——物理关节——角度关节驱动 二、案例&#xff1a;做一个“能开合的门” 1…

VSCode - 一键删除每行前面的行号数字

ctrl f 打开查找 输入正则表达式&#xff0c;并点击使用正则查找&#xff1a; 带点的&#xff1a;^\s*([0-9])\. 不带点&#xff1a;^\s*([0-9]) 综合起来&#xff1a;^\s*([0-9])[\.]* 替换为空格

【Java】集合List的toArray()方法及其重载

在Java中&#xff0c;集合&#xff08;List 接口的实现类&#xff09;提供了一个名为 toArray 的方法&#xff0c;用于将集合中的元素转换成数组。该方法有两个主要的重载形式&#xff0c;分别用于不同的情况。 toArray()重载方法1 <T> T[] toArray(T[] a)这个方法将集…

windows10 docker 安装在D盘

win10安装docker后发现c盘空间急速减少&#xff0c;360管家查看发现images镜像安装在C盘&#xff0c;于是重装docker desktop以为在安装过程中能够选择&#xff0c;遗憾的是没有提供选择权限&#xff0c;默认直接就安装到了c盘。 desktop 迁移 百度得知可以将c盘的docker安装…

数字电路-二进制学习

什么是二进制&#xff1f; 数字电路 中 只有 高电平 和低电平 就是 1 和0 进位规则是“逢二进一”&#xff0c;借位规则是“借一当二”。 二进制、八进制 、十进制、十六进制 二进制 有两个数来表示 &#xff1a; 0、1 八进制 有8个数来表示 &#xff1a; 0、1、2、3、4、…

RabbitMQ---Spring AMQP

Spring AMQP 1. 简介 Spring有很多不同的项目&#xff0c;其中就有对AMQP的支持&#xff1a; Spring AMQP的页面&#xff1a;http://spring.io/projects/spring-amqp 注意这里一段描述&#xff1a; Spring-amqp是对AMQP协议的抽象实现&#xff0c;而spring-rabbit 是对协…

Android开发系列课程---序言

1.本专栏致力于Android从入门到高级的课程学习。涉及到Android开发常用基础组件&#xff0c;也有Android开发必备框架的学习。是一个从0到1&#xff0c;从小白到高手的进阶课程。博主十年Android实战经验&#xff0c;课程内容全部来自于实战。学完基础课程&#xff0c;能顺利上…

rancher界面无法登陆问题解决,登录超时;

1.找到rancher主机&#xff0c;查看日志 docker ps | grep rancher # rancher 容器 名称 jolly_ptolemy docker logs -f jolly_ptolemy 日志提示&#xff0c; java.sql.SQLException: Got error 28 from storage engine&#xff0c;磁盘满了 2.磁盘管理 df -h #查看磁盘使…

串口接收数据-控制LED灯

目标 通过串口接收数据&#xff0c;对数据分析&#xff0c;控制8个LED灯按照设定时间闪烁。 8个LED灯可以任意设计&#xff0c;是否闪烁。闪烁时间按ms计算&#xff0c;通过串口发送&#xff0c;可设置1~4,294,967,296ms&#xff0c;也就是4字节数据协议自拟&#xff0c;有数…

手机云控设计思路

本系统为任务分发系统,上游发布任务或者接受其他平台系统分发的任务,对任务进行规则引擎处理后分类,由核心分发系统部分进行对存活的空闲终端进行分发任务,终端做完任务后进行反馈给任务系统. 核心要处理的点是终端存活与空闲的统计、任务平均分布下发给终端的算法,保证分布的…

智能网联汽车场景数据图像标注要求及方法

1 范围 本标准规定了智能网联汽车场景数据图像中交通参与者、交通信号灯、交通标志、交通标线、可行驶区域、光照条件、遮挡截断情况7类元素的标注要求及方法。 本标准适用于智能网联汽车图像数据标注。 2 规范性引用文件 下列文件对于本文件的应用是必不可少的。凡是注日…

Unity——音乐、音效

在游戏运行的过程中&#xff0c;音效的播放时机与游戏当前内容密切相关&#xff0c;而且随着场景的变化、剧情的推进&#xff0c;背景音乐也需要适时切换&#xff0c;所以恰当地控制音乐和音效的播放非常重要。音乐和音效的播放、停止、切换和音量变化等&#xff0c;都需要由脚…

《向量数据库指南》——大模型时代向量数据库是刚需吗?

目录 从实际应用的角度来看 从技术发展的角度来看 如果你问我,我会毫不犹豫地回答:“是的,向量数据库是刚需。”为什么?听我慢慢给你解释。 首先,我们要理解什么是向量数据库。向量数据库是一种专门用于存储和查询向量数据的数据库。这些向量数据可以是文本、图像、音频…

4.RabbitMQ高级特性 幂等 可靠消息 等等

一、如何保证生产者生产消息100%的投递成功 保障消息的成功发出保障MQ节点的成功接收发送端收到MQ节点&#xff08;Broker&#xff09;确认应答完善的消息进行补偿机制 1. 理解Confirm确认消息机制 消息的确认&#xff0c;是指生产者投递消息后&#xff0c;如果Broker收到消…