【Spring】Spring循环依赖的处理

news2024/12/27 0:03:30

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

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

@Service
public class TestService1 {

    @Autowired
    private TestService2 testService2;

    public void test1() {
    }
}

@Service
public class TestService2 {

    @Autowired
    private 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.coloradmin.cn/o/914414.html

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

相关文章

数学建模(四)整数规划—匈牙利算法

一、0-1型整数规划问题 1.1 案例 投资问题: 有600万元投资5个项目,收益如表,求利润最大的方案? 设置决策变量: 模型: 指派问题: 甲乙丙丁四个人,ABCD四项工作,要求每人只能做一项…

Linux系统安全——NAT(SNAT、DNAT)

目录 NAT SNAT SNAT实际操作 DNAT DNAT实际操作 NAT NAT: network address translation,支持PREROUTING,INPUT,OUTPUT,POSTROUTING四个链 请求报文:修改源/目标IP, 响应报文:修改源/目标…

【jvm】双亲委派机制

目录 一、说明二、工作原理三、图示 一、说明 1.java虚拟机对class文件采用的是按需加载的方式,当需要使用该类时才会将它的class文件加载到内存生成class对象 2.加载某个类的class文件时,java虚拟机采用双亲委派模式,即把请求交给由父类处理…

2023年计算机设计大赛国三 数据可视化 (源码可分享)

2023年暑假参加了全国大学生计算机设计大赛,并获得了国家三等奖(国赛答辩出了点小插曲)。在此分享和记录本次比赛的经验。 目录 一、作品简介二、作品效果图三、设计思路四、项目特色 一、作品简介 本项目实现对农产品近期发展、电商销售、灾…

【QT5-自我学习-线程qThread练习-两种使用方式-1:通过继承线程类来使用-基础样例】

【QT5-自我学习-线程qThread练习-两种使用方式-1:通过继承线程类来使用-基础样例】 1、前言2、实验环境3-1、学习链接-参考文章3-2、先前了解-自我总结(1)线程处理逻辑事件,不能带有主窗口的事件(2)一般考虑…

Debootstrap 教程

文章目录 Debootstrap 教程安装 debootstrap使用 debootstrap运行 debootstrap进入新的系统结束语 Debootstrap 教程 debootstrap 是一个用于在 Debian-based 系统上创建一个基本的 Debian 系统的工具。它可以用于创建 chroot 环境、容器或者为新的系统安装做准备。 安装 deb…

数学建模-模型详解(2)

微分模型 当谈到微分模型时,通常指的是使用微分方程来描述某个系统的动态行为。微分方程是描述变量之间变化率的数学方程。微分模型可以用于解决各种实际问题,例如物理学、工程学、生物学等领域。 微分模型可以分为两类:常微分方程和偏微分…

基于Linux操作系统中的shell脚本

目录 前言 一、概述 1、什么是shell? 2、shell脚本的用途有哪些? 3、常见的shell有哪些? 4、学习shell应该从哪几个方面入手? 4.1、表达式 1)变量 2)运算符 4.2、语句 1)条件语句&am…

【LeetCode-中等题】3. 无重复字符的最长子串

题目 题解一:单指针,滑动窗口 思路: 设置一个左指针,来判断下一个元素是否在set集合中,如果不在,就加入集合,right继续,如果在,就剔除重复的元素,计算串的长度…

C++笔记之设计模式:setter函数、依赖注入

C笔记之设计模式:setter函数、依赖注入 code review! 文章目录 C笔记之设计模式:setter函数、依赖注入1.概念2.基本示例3.setter函数4.基本示例setter函数构成依赖注入5.概念——ChatGpt6.构造函数注入示例7.接口注入示例8. 构造函数注入的使用场景和用…

【C++】早绑定、析构与多态 | 一道关于多态的选择题记录

今天在和群友聊天的时候看到了一道很坑的题目&#xff0c;分享给大家 1.看题&#xff01; 先来看看题目 struct Dad { public:Dad(){ echo();}~Dad(){ echo();}virtual void echo() {cout << "DAD ";} };struct Son:Dad { public:void echo() const override…

ARM,(cortex-A7核中断实验)

1.实验目的&#xff1a;实现KEY1/LEY2/KE3三个按键&#xff0c;中断触发打印一句话&#xff0c;并且灯的状态取反&#xff1b; key1 ----> LED3灯状态取反&#xff1b; key2 ----> LED2灯状态取反&#xff1b; key3 ----> LED1灯状态取反&#xff1b; 2.分析框图: …

<深度学习基础> 激活函数

为什么需要激活函数&#xff1f;激活函数的作用&#xff1f; 激活函数可以引入非线性因素&#xff0c;可以学习到复杂的任务或函数。如果不使用激活函数&#xff0c;则输出信号仅是一个简单的线性函数。线性函数一个一级多项式&#xff0c;线性方程的复杂度有限&#xff0c;从…

vue3 01-setup函数

1.setup函数的作用: 1.是组合式api的入口2.比beforeCreate 执行更早3.没有this组件实例一开始创建vue3页面的时候是这样的 <template></template> <script> export default{setup(){return{ }} } </script>给容器传参在页面中显示 数据给模板使用,以…

【C语言】位段,枚举和联合体详解

目录 1.位段 1.1 什么是位段 1.2 位段的内存分配 1.3 位段的跨平台问题 2.枚举 2.1 枚举类型的定义 2.2 枚举的优点 3. 联合&#xff08;共用体&#xff09; 3.1 联合类型的定义 3.2 联合的特点 3.3 联合大小的计算 1.位段 1.1 什么是位段 位段的声明和结构体是类…

基于ECharts+flask的爬虫可视化

项目效果。 本案例基于python的flask框架&#xff0c;通过爬虫程序将数据存储在csv文件中&#xff0c;在项目运行时会通过render_template映射出对应的页面&#xff0c;并且触发一个函数&#xff0c;该函数会读取csv文件的数据将之交给echarts渲染 &#xff0c;echarts将之渲染…

线性代数的学习和整理---番外1:EXCEL里角度,弧度,三角函数

目录 1 角的度量&#xff1a;角度和弧度 1.1 角度 angle 1.1.1 定义 1.1.2 公式 1.1.2 角度取值范围 1.2 弧长和弦长 1.3 弧度 rad 1.3.1 弧长和弧度定义的原理 1.3.2 定义 1.3.3 取值范围 1.3.4 取值范围 1.4 角度&#xff0c;弧度的换算 1.5 EXCEL里进行角度和…

Red Hat Enterprise Linux (RHEL) 6.4 安装、redhat6.4安装

1、下载地址 Red Hat Enterprise Linux (RHEL) 6.4 DVD ISO 迅雷下载地址http://rhel.ieesee.net/uingei/rhel-server-6.4-x86_64-dvd.iso 2、创建虚拟机 3、redhat安装 选择第一个安装 Skip跳过检查 语言选择简体中文 键盘选择默认 选择基本存储设备 忽略所有数据 设置root密…

Ribbon:listOfServers

解释&#xff1a; 配置了address的地址,请求会走address&#xff0c;也就是http://127.0.0.1:8081&#xff0c;通常用户与别的后端服务进行联调设置为其本地服务的ip。 如果将address:注释掉。 会走后面的XXX.feign.default-server地址&#xff0c;这个地址通常可以配一个网关…

基于Spring Boot的智慧团支部建设网站的设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的智慧团支部建设网站的设计与实现&#xff08;Javaspring bootMySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java sp…