当前位置: 首页 > news >正文

Spring的三级缓存如何解决循环依赖问题

循环依赖问题是在对象之间存在相互依赖关系,形成一个闭环,导致无法准确的完成对象的创建和初始化,当两个或多个对象彼此之间相互引用,这种相互引用形成一个循环时,就可能出现循环依赖问题。

Spring 框架中,循环依赖(Circular Dependency)是指两个或多个 Bean 之间互相依赖,导致依赖关系形成一个闭环。例如:

  • Bean A 依赖 Bean B
  • Bean B 又依赖 Bean A

这种依赖会导致 Spring 无法正确实例化和初始化这些 Bean,因为在创建一个 Bean 时需要先创建它所依赖的 Bean,而它依赖的 Bean 又反过来依赖它


如何解决循环依赖

单例作用域的循环依赖,依赖于三级缓存来解决问题

  • 一级缓存(Singleton Objects): 存放已经完全初始化的单例 Bean。
  • 二级缓存(Early Singleton Objects): 存放原始的、尚未完全初始化的 Bean 实例(暴露了部分 Bean 的引用)。
  • 三级缓存(Singleton Factories): 存放 Bean 的对象工厂,延迟初始化

解决循环依赖的前提条件

  1. 互相依赖的Bean必须要是单例的Bean
  2. 依赖注入的方式不能都是构造函数注入的方式

当遇到循环依赖时,Spring 采取以下步骤

1.创建 Bean 的原始实例

  • Spring 首先根据构造器或工厂方法创建 Bean 的原始实例(即还未完成依赖注入和初始化)。
  • 这个实例此时不会立即暴露给其他 Bean。
  • ObjectFactory 放入三级缓存
  • Spring 会将一个能够生成该 Bean 的工厂对象(ObjectFactory放入三级缓存(singletonFactories)。

2.检测并解决依赖

  • 如果依赖的 Bean 已经创建,则直接从一级缓存(singletonObjects)中获取。
  • 如果依赖的 Bean 尚未完全初始化但已创建原始实例,Spring 会从三级缓存中通过 ObjectFactory 获取早期引用,并将其放入二级缓存(earlySingletonObjects)。
  • 从二级缓存中获取的 Bean 引用可能是代理对象,用于避免后续初始化重复。

3.完成依赖注入

  • 使用从一级缓存或二级缓存中获取的 Bean 引用,完成当前 Bean 的依赖注入。

4.完成 Bean 初始化

  • 初始化后,Spring 会将完全初始化的 Bean 放入一级缓存(singletonObjects),并从二级缓存和三级缓存中移除相关引用


为什么一定要使用三级缓存

1.首先,一级缓存一定是要的,因为Bean是单例模式,需要存放到某个容器中,而一级缓存就是这个缓存容器。

2.二级缓存可以不要,我们可以把半成品Bean放到一级缓存中,但这样需要给一级缓存中添加标识,标识哪些是完整对象,哪些都是半成品对象,这样有几个问题:                                        1.增加了Spring源码设计复杂性。                                                                                              2.在查询时,需要先判断标识,查询效率变低了。                                                                    3.违反单一设计原则。

因此为了解决这些问题,二级缓存也是必须要的。

3.三级缓存也可以不要,但这样也有一个问题,那就是Spring的设计模式中,在生成代理时,为了实现对象初始化和生成代理对象的解耦                                                                                     所以代理对象是在AnnotationAwareAspectJAutoProxyCreator 这个后置处理的最后一步生成AOP代理对象的。

如果不要三级缓存,那么我们需要在所有类创建之前,先将代理类创建出来,这样遇到循环依赖就可以直接拿出代理对象来使用了,但这种方式的缺点是打破了原理Spring 的设计理念。(实现对象初始化和生成代理对象的解耦)

所以最优方案是,不提前创建代理对象,而是使用三级缓存存储创建对象的表达式,等遇到循环依赖,再按照Spring的设计模式来生成代理对象。

相关文章:

Spring的三级缓存如何解决循环依赖问题

循环依赖问题是在对象之间存在相互依赖关系,形成一个闭环,导致无法准确的完成对象的创建和初始化,当两个或多个对象彼此之间相互引用,这种相互引用形成一个循环时,就可能出现循环依赖问题。 在 Spring 框架中&#xf…...

Ext文件系统

文件内容属性 被打开的文件在内存中,没有被打开的文件在磁盘里文件系统的工作就是根据路径帮我们找到在磁盘上的文件 磁盘(硬件) 磁盘的存储结构 磁头在传动臂的运动下共同进退,向磁盘写入的时候是向柱面批量写入的 OS文件系统访…...

回溯算法---数独问题

回溯算法理论基础 回溯和递归密不可分,有回溯就有递归,所谓回溯就是基于一个叉树,可能是二叉树或者是三叉树,从root节点开始深度优先搜索遍历节点,当遍历到一个子节点时,回溯到上一个根节点选择另外一个子…...

蓝桥杯python基础算法(2-1)——排序

目录 一、排序 二、例题 P3225——宝藏排序Ⅰ 三、各种排序比较 四、例题 P3226——宝藏排序Ⅱ 一、排序 (一)冒泡排序 基本思想:比较相邻的元素,如果顺序错误就把它们交换过来。 (二)选择排序 基本思想…...

【课程笔记】信息隐藏与数字水印

文章总览:YuanDaiMa2048博客文章总览 【课程笔记】信息隐藏与数字水印 信号处理基础知识隐写系统隐写算法性能指标音频信号处理基础数字音频概念人类听觉系统与语音质量评价信息隐藏的原理数字指纹与版权保护盲水印与非盲水印私钥水印与公钥水印信息隐藏的研究层次信息隐藏与数…...

Page Assist实现deepseek离线部署的在线搜索功能

前面文章Mac 基于Ollama 本地部署DeepSeek离线模型 实现了deepseek的离线部署,但是部署完成虽然可以进行问答和交互,也有thinking过程,但是没办法像官方一样进行联网搜索。今天我们介绍一款浏览器插件Page Assist来实现联网搜索,完…...

composeUI中Box 和 Surface的区别

在 Jetpack Compose 中,Box 和 Surface 都是常用的布局组件,但它们的用途和功能有所不同。 Box 组件: 功能:Box 是一个用于将子组件堆叠在一起的布局容器,类似于传统 Android 中的 FrameLayout。用途:适用…...

【LeetCode】5. 贪心算法:买卖股票时机

太久没更了,抽空学习下。 看一道简单题。 class Solution:def maxProfit(self, prices: List[int]) -> int:cost -1profit 0for i in prices:if cost -1:cost icontinueprofit_ i - costif profit_ > profit:profit profit_if cost > i:cost iret…...

MySQL表的CURD

目录 一、Create 1.1单行数据全列插入 1.2多行数据指定列插入 1.3插入否则更新 1.4替换 2.Retrieve 2.1 select列 2.1.1全列查询 2.1.2指定列查询 2.1.3查询字段为表达式 2.1.4为查询结果指定别名 2.1.5结果去重 2.2where条件 2.3结果排序 2.4筛选分页结果 三…...

Java 如何覆盖第三方 jar 包中的类

目录 一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理 背景: 在我们日常的开发中,经常需要使用第三方的 jar 包,有时候我们会发现第三方的 jar 包中的某一个类有问题,或者我们需要定制化修改其中的逻辑&#xff0c…...

VSCode中使用EmmyLua插件对Unity的tolua断点调试

一.VSCode中搜索安装EmmyLua插件 二.创建和编辑launch.json文件 初始的launch.json是这样的 手动编辑加上一段内容如下图所示: 三.启动调试模式,并选择附加的进程...

【数据结构】_链表经典算法OJ(力扣/牛客第二弹)

目录 1. 题目1:返回倒数第k个节点 1.1 题目链接及描述 1.2 解题思路 1.3 程序 2. 题目2:链表的回文结构 2.1 题目链接及描述 2.2 解题思路 2.3 程序 1. 题目1:返回倒数第k个节点 1.1 题目链接及描述 题目链接: 面试题 …...

Spring Boot 2 快速教程:WebFlux优缺点及性能分析(四)

WebFlux优缺点 【来源DeepSeek】 Spring WebFlux 是 Spring 框架提供的响应式编程模型,旨在支持非阻塞、异步和高并发的应用场景。其优缺点如下: 优点 高并发与低资源消耗 非阻塞 I/O:基于事件循环模型(如 Netty)&am…...

自定义多功能输入对话框:基于 Qt 打造灵活交互界面

一、引言 在使用 Qt 进行应用程序开发时,我们经常需要与用户进行交互,获取他们输入的各种信息。QInputDialog 是 Qt 提供的一个便捷工具,可用于简单的输入场景,但当需求变得复杂,需要支持更多类型的输入控件&#xff0…...

基于springboot河南省旅游管理系统

基于Spring Boot的河南省旅游管理系统是一种专为河南省旅游行业设计的信息管理系统,旨在整合和管理河南省的旅游资源信息,为游客提供准确、全面的旅游攻略和服务。以下是对该系统的详细介绍: 一、系统背景与意义 河南省作为中国的中部省份&…...

LabVIEW图像采集与应变场测量系统

开发了一种基于LabVIEW的图像采集与应变场测量系统,提供一种高精度、非接触式的测量技术,用于监测物体的全场位移和应变。系统整合了实时监控、数据记录和自动对焦等功能,适用于工程应用和科学研究。 项目背景 传统的位移和应变测量技术往往…...

CommonAPI学习笔记-2

一. 概述 ​ 这篇文章主要是想整理并且分析CommonAPI代码生成工具根据fidl和fdepl配置文件生成出来的代码的结构和作用。 二. fidl ​ 用户根据业务需求在fidl文件中定义业务服务接口的结构以及自定义数据类型,然后使用core生成工具传入fidl文件生成该fidl的核心…...

ISP代理与住宅代理的区别

代理充当用户和互联网之间的中介,在增强安全性、隐私和可访问性方面提供多种功能。在众多代理类型中,ISP和住宅代理脱颖而出,各自拥有不同的功能和应用程序。 一、ISP代理 ISP代理,俗称Internet服务提供商代理,通过其…...

[25] cuda 应用之 nppi 实现图像色彩调整

[25] cuda 应用之 nppi 实现图像色彩调整 在 NPPI(NVIDIA Performance Primitives)中,图像色彩调整通常包括以下几种操作: 亮度调整:增加或减少图像的亮度。对比度调整:增强或减弱图像的对比度。饱和度调整:增强或减弱图像的颜色饱和度。色调调整:改变图像的色调(通常…...

Java 大视界 -- Java 大数据在智慧文旅中的应用与体验优化(74)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...

PyTorch快速入门

Anaconda Anaconda 是一款面向科学计算的开源 Python 发行版本,它集成了众多科学计算所需的库、工具和环境管理系统,旨在简化包管理和部署,提升开发与研究效率。 核心组件: Conda:这是 Anaconda 自带的包和环境管理…...

100.7 AI量化面试题:如何利用新闻文本数据构建交易信号?

目录 0. 承前1. 解题思路1.1 数据处理维度1.2 分析模型维度1.3 信号构建维度 2. 新闻数据获取与预处理2.1 数据获取接口2.2 文本预处理 3. 情感分析与事件抽取3.1 情感分析模型3.2 事件抽取 4. 信号生成与优化4.1 信号构建4.2 信号优化 5. 策略实现与回测5.1 策略实现 6. 回答话…...

CF 465B.Inbox (100500)(Java实现)

题目分析 计算读取所有未读邮件所需的步数,其中1代表未读,0代表已读 思路分析 遍历邮件,如果当前是未读,那么所需步数1,如果下一封也是未读,不用管(遍历后会直接1),如果下一封是已读&#xff0…...

微信小程序获取openid和其他接口同时并发请求如何保证先获取到openid

在微信小程序中,如果你需要并发请求获取 openid 和其他接口的数据,并且希望确保先获取到 openid 之后再进行后续操作,可以考虑以下几种方法: 方法一:使用 Promise 链 1, 先请求 openid:使用 Promise 来请求 openid。 2, 在获取到 openid 后再请求其他接口。 function g…...

实现动态卡通笑脸的着色器实现

大家好!我是 [数擎 AI],一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步! 开发领域:前端开发 | A…...

DeepSeek R1 模型解读与微调

DeepSeek R1 模型是 DeepSeek 团队推出的一款重要的大语言模型,旨在通过强化学习提升大型语言模型的推理能力。 模型架构 DeepSeek-R1-Zero DeepSeek-R1-Zero 是 DeepSeek 团队推出的第一代推理模型,完全依靠强化学习(RL)训练&…...

YOLOv11实时目标检测 | 摄像头视频图片文件检测

在上篇文章中YOLO11环境部署 || 从检测到训练https://blog.csdn.net/2301_79442295/article/details/145414103#comments_36164492,我们详细探讨了YOLO11的部署以及推理训练,但是评论区的观众老爷就说了:“博主博主,你这个只能推理…...

Node.js学习指南

一、模块化规范 nodejs使用的模块化规范 叫做 common.js 规范: 每一个模块都有独立的作用域 代码在各自模块中执行 不会造成全局污染 每一个模块都是一个独立的文件(module对象) 模块可以被多次加载(module.exports 属性) 但是仅…...

2.5学习总结

今天看了二叉树&#xff0c;看的一脸懵&#xff0c;写了两道题 P4913&#xff1a;二叉树深度 #include <stdio.h> #include <stdlib.h> struct hly {int left;int right; }tree[1000005]; int hulingyun(int x) {if(x0)return 0;return 1max(hulingyun(tree[x].le…...

java进阶文章链接

java 泛型&#xff1a;java 泛型详解-绝对是对泛型方法讲解最详细的&#xff0c;没有之一 Java 泛型&#xff0c;你了解类型擦除吗&#xff1f; java 注解&#xff1a;深入理解Java注解类型 秒懂&#xff0c;Java 注解 &#xff08;Annotation&#xff09;你可以这样学 jav…...