Spring 的循环依赖

在 Spring 中,循环依赖是指两个或多个 Bean 相互依赖,导致在创建过程中出现了依赖死锁的问题。为了解决循环依赖,Spring 引入了三级缓存机制。了解为什么需要三级缓存机制,首先要明白循环依赖是如何发生的,以及两级缓存为什么不足够。

一、循环依赖是什么?

假设有两个 Bean AB

  • A 依赖于 B
  • B 依赖于 A

如果没有缓存机制,Spring 在创建 A 时会发现它需要 B,于是去创建 B,但在创建 B 时又发现需要 A,这时就会产生循环依赖,最终导致栈溢出或抛出异常。

二、三级缓存机制

Spring 使用三级缓存(三级依赖处理机制)来解决循环依赖问题,分别是:

  1. 一级缓存singletonObjects,用于存储完全初始化好的单例对象。

    • 完全初始化后的 Bean 会放入一级缓存中,表示该 Bean 已经准备好可以使用了。
  2. 二级缓存earlySingletonObjects,用于存储提前暴露的 Bean,主要是尚未完成依赖注入但已经实例化的 Bean。

    • 这个缓存用于提前暴露尚未完成初始化的 Bean,防止循环依赖无法解决。通常情况下,如果某个 Bean 已经实例化但还没有完成后续的属性填充等操作,它会存放在这个缓存中。
  3. 三级缓存singletonFactories,用于存储 Bean 的 ObjectFactory(对象工厂),这个工厂提供对该 Bean 的代理对象(比如 AOP 代理对象)的创建逻辑。

    • 三级缓存的存在使得 Spring 可以在 Bean 创建的早期阶段将未完全初始化的 Bean 提供出来,尤其是代理对象。这样即使 Bean 还没有完成依赖注入,也能通过工厂获得它的一个早期引用。

三、为什么需要三级缓存?两级不行吗?

假如只使用一级缓存和二级缓存:

  • 一级缓存只存储已经完全初始化好的 Bean,显然无法解决循环依赖问题,因为 Bean 尚未完成初始化时无法放入一级缓存。
  • 二级缓存则存储提前暴露的 Bean,但这通常是直接的原始对象,而不是代理对象。如果应用了 AOP 或者需要创建代理对象的场景中,依赖的 Bean 如果在循环依赖中被提前暴露时,可能无法应用正确的代理。

三级缓存 允许通过 ObjectFactory 这种延迟加载的方式,在需要的时候创建早期引用,包括创建代理对象。这确保了即使在循环依赖中,Spring 也可以在合适的时间点创建完整的代理对象,而不是仅仅提供原始对象。

四、总结

三级缓存机制的关键点在于:

  • 二级缓存不能解决 Bean 代理的问题,特别是在涉及到 AOP 的情况下。
  • 三级缓存通过引入 ObjectFactory,可以确保在代理场景下也能处理循环依赖,提前暴露还未完全初始化的代理对象。

因此,两级缓存不足以解决所有循环依赖问题,特别是在涉及到代理对象的情况下,三级缓存的机制显得非常必要。

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

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

相关文章

Python类及元类的创建流程

Python类及元类的创建流程 代码运行结果再看type和object的关系和约定type和object具有的方法不一样看代码和运行结果,可以完全理解python的执行过程。再补充几点, 代码 class MetaCls(type):print(0>>>, MetaCls, 0)def __init__(self, name,…

uniapp vue3 梯形选项卡组件

实现的效果图&#xff1a; 切换选项卡显示不同的内容&#xff0c;把这个选项卡做成了一个组件&#xff0c;需要的自取。 // 组件名为 trapezoidalTab <template> <view class"pd24"><view class"nav"><!-- 左侧 --><view cla…

idea启动oom了解决

解决 Error:java: java.lang.OutOfMemoryError: WrappedJavaFileObject[org.jetbrains.jps.javac.InputFileObject[file:///D:/mingan/pb/backend/src/main/java/com/cy/backend/service/impl/StorageServiceImpl.java]]pos36199: WrappedJavaFileObject[org.jetbrains.jps.j…

你是不是分不清哪些字体是商用,哪些非商用?快来看,免得莫名其妙负债。

前言 最近发现有好多小伙伴在做PPT的时候&#xff0c;都有一个很不好的习惯&#xff1a;没有调整好字体。 这里说的没有调整好字体的意思是&#xff1a;在一些公开发布的内容上使用一些可能造成侵权的字体。 字体侵权‌的后果相当严重。轻者可能面临法律纠纷&#xff0c;重者…

consul服务注册发现与配置中心

目录 1 consul安装与运行 1.1 下载方式 1.2 安装 1.3 启动 1.4 访问方式 2 consul 实现服务注册与发现 2.1 引入 2.2 服务注册 2.3 服务发现 3 consul配置中心 3.1 基础配置 Eureka已经停止更新了&#xff0c;consul是独立且和微服务功能解耦的注册中心&#xff0c;…

Nginx配置虚拟主机

基于域名的虚拟主机 修改配置 进入nginx里的conf目录 修改nginx配置文件nginx.conf vi nginx.conf worker_processes auto;(自动识别CPU数) worker_rlimit_nofile 20480;&#xff08;指定 worker 子进程可以打开的最大文件句柄数&#xff0c;默认为1024&#xff09; use …

杀死端口占用的进程

1、查看端口的进程&#xff0c;以9023为例 &#xff08;1&#xff09;方法1 netstat -tunpl|grep 9023 &#xff08;2&#xff09;方法2 ss -tulpan |grep 9023 &#xff08;3&#xff09;方法3 netstat -ntlp |grep 9023 &#xff08;4&#xff09;方法4 lsof -i:9023 …

百度移动刷下拉词工具:快速出下拉词的技术分析

都2024年了&#xff0c;你还在做SEO百度下拉&#xff1f;答案当然是肯定的&#xff0c;虽然百度的搜索流量不如从前&#xff0c;但移动端的流量依然是巨大的&#xff01;除了百度SEO快排以外&#xff0c;下拉也是一大流量入口&#xff0c;尤其是在移动端搜索的流量越来越大时&a…

计算机组成原理-数值的表示与运算(进制)

在冯诺依曼体系结构中&#xff0c;计算机的3个特点中&#xff0c;有软件以二进制&#xff08;2#&#xff09;的形式表示&#xff0c;也就是数据以二进制的形式存入计算机中 其运算规则为 在有符号数中&#xff1a;1.xxx表示-0.xxx&#xff0c;1表示负号 上述的小数点是我们的认…

鸿蒙手势交互(三:组合手势)

三、组合手势 由多种单一手势组合而成&#xff0c;通过在GestureGroup中使用不同的GestureMode来声明该组合手势的类型&#xff0c;支持顺序识别、并行识别和互斥识别三种类型。 GestureGroup(mode:GestureMode, gesture:GestureType[]) //- mode&#xff1a;为GestureMode枚…

vue2中字符串动态拼接字段给到接口

【设计初衷是用户可根据给定的字段进行准确描述】 实现功能&#xff1a; 1. 文本域内容串动态配置字段&#xff0c;以$ {英文}拼接格式给到接口。 &#xff08;传参如&#xff1a;$ {heat_status_code}正常&#xff0c;$ {wdy_temp}也正常&#xff01;&#xff09; 2. 编辑时根…

table表格,让thead固定,tbody内容滚动,关键是都对齐的纯css写法

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f…

Postman如何测试WebSocket接口!

01、WebSocket 简介 WebSocket是一种在单个TCP连接上进行全双工通信的协议。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。在WebSocket API中&#xff0c;浏览器和服务器只需要完成一次握手&#xff0c;两者之间就直…

【Linux 20】线程控制

文章目录 &#x1f308; 一、创建线程⭐ 1. 线程创建函数⭐ 2. 创建单线程⭐ 3. 给线程传参⭐ 4. 创建多线程⭐ 5. 获取线程 ID &#x1f308; 二、终止线程⭐1. 使用 return 终止线程⭐ 2. 使用 pthread_exit 函数终止线程⭐ 3. 使用 pthread_cancel 函数终止线程 &#x1f30…

HTTP协议详解以及常见的状态码

HTTP协议的定义&#xff1a; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是一种建立在TCP&#xff08;传输控制协议&#xff09;之上的无状态连接协议。它是互联网的基础协议之一&#xff0c;用于客户端与服务器之间的通信。HTTP规定…

【Python】练习:控制语句(二)第1关

第1关&#xff1a;分支结构基础实训 第一题第二题第三题第四题&#xff08;※&#xff09;第五题&#xff08;※&#xff09;第六题第七题 第一题 #第一题 for temp in [-280, -100, 0, 20, 120, 200]:#请在下面编写代码# ********** Begin ********** #if temp>-273.15:F9/…

如何选择适合客户运营团队的帮助中心搭建工具?8款工具盘点

在竞争激烈的商业环境中&#xff0c;客户运营团队需要高效、便捷的工具来搭建帮助中心&#xff0c;以提升客户服务质量和用户体验。选择合适的帮助中心搭建工具&#xff0c;不仅能提高团队工作效率&#xff0c;还能增强客户满意度和忠诚度。本文将为您盘点八款适合客户运营团队…

中间件安全(二)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言: 前文链接&#xff1a;中间件安全&#xff08;一&#xff09; 本文主要讲解Couchdb数据库未授权越权漏洞&#xff08;CVE-2017-12635&#xff09;。 靶场链接&#xff1a;Vu…

爱普生相机SD卡格式化后数据恢复指南

我借了朋友的‌爱普生相机&#xff0c;想查看一下内存&#xff0c;哎呀&#xff0c;一不小心按错了&#xff0c;竟然执行了格式化操作&#xff0c;这可真是太让人郁闷了&#xff0c;这还有机会挽救数据吗&#xff1f;心塞&#xff0c;求帮助&#xff01; 随着数码摄影的普及&am…

java框架

Oozie任务调度框架 Hue hadoop的WEB工具 seatunnel 数据同步框架 TIDB 大数据库支持事物 StreamX fink和spark的集成 OceanBase 阿里巴巴数据库 dooringx-lib、AntV 可视化H5工具 lowcode、Appsmith&#xff08;推荐&#xff09;、nocoBase 、Budibase、taskbuilder 低代…