Spring 为何需要三级缓存解决循环依赖,而不是二级缓存

news2025/3/3 5:06:15

Spring 使用三级缓存来解决循环依赖问题,而不是仅使用二级缓存,主要是为了同时满足依赖注入和 AOP 代理的需求。以下是详细解释:

### Spring 三级缓存的作用
Spring 的三级缓存分别用于不同的场景:
1. **一级缓存(`singletonObjects`)**:存放完全初始化完成的单例 Bean。
2. **二级缓存(`earlySingletonObjects`)**:存放提前暴露的半成品 Bean,用于解决循环依赖。
3. **三级缓存(`singletonFactories`)**:存放 Bean 的工厂对象,用于动态生成半成品 Bean 或代理对象。

### 为什么需要三级缓存
如果仅使用二级缓存(存放半成品 Bean),虽然可以在一定程度上解决循环依赖问题,但会面临以下问题:
1. **无法支持 AOP 代理**:
   - 如果 Bean 需要被 AOP 代理(例如使用了 `@Transactional` 或其他 AOP 功能),Spring 需要在 Bean 初始化之前生成代理对象。
   - 如果只有二级缓存,注入的将是原始 Bean,而不是代理对象,这会导致后续的 AOP 功能失效。

2. **Bean 生命周期管理冲突**:
   - 在 Spring 的生命周期中,Bean 的代理对象通常是在初始化阶段生成的。
   - 如果仅使用二级缓存,无法在 Bean 初始化之前动态决定返回原始对象还是代理对象。

通过三级缓存,Spring 可以在 Bean 初始化之前通过工厂对象动态生成代理对象,并将其放入二级缓存,从而确保注入的始终是正确的对象。

### 三级缓存的流程
以 A 和 B 的循环依赖为例:
1. **创建 A**:
   - 实例化 A,并将 A 的工厂对象放入三级缓存。
2. **填充 A 的属性**:
   - 发现 A 依赖 B,开始创建 B。
3. **创建 B**:
   - 实例化 B,并将 B 的工厂对象放入三级缓存。
4. **填充 B 的属性**:
   - 发现 B 依赖 A,从三级缓存中获取 A 的工厂对象,生成半成品 A,并放入二级缓存。
   - 将半成品 A 注入到 B 中,完成 B 的初始化。
5. **完成 B 的初始化**:
   - 将 B 放入一级缓存。
6. **完成 A 的初始化**:
   - 从一级缓存中获取 B,注入到 A 中,完成 A 的初始化。

### 为什么二级缓存不够
如果仅使用二级缓存:
1. **无法支持 AOP 代理**:注入的将是原始对象,而不是代理对象。
2. **性能问题**:每次都需要通过工厂对象生成 Bean,性能较差。

### 总结
Spring 使用三级缓存是为了同时解决循环依赖和 AOP 代理的需求。三级缓存通过动态生成代理对象并提前暴露半成品 Bean,确保了依赖注入的正确性和 AOP 功能的完整性。

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

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

相关文章

2继续NTS库学习(读取shapefile)

引用库如下: 读取shapefile代码如下: namespace IfoxDemo {public class Class1{[CommandMethod("xx")]public static void nts二次学习(){Document doc Application.DocumentManager.MdiActiveDocument;var ed doc.Editor;string shpPath …

JavaWeb后端基础(3)

原打算把Mysql操作数据库的一些知识写进去,但是感觉没必要,要是现在会的都是简单的增删改查,所以,这一篇,我直接从java操作数据库开始写,所以这一篇大致就是记一下JDBC、MyBatis、以及SpringBoot的配置文件…

Vue程序下载

Vue是一个基于JavaScript(JS)实现的框架,想要使用它,就得先拿到Vue的js文件 Vue官网 Vue2:Vue.js Vue3:Vue.js - 渐进式 JavaScript 框架 | Vue.js 下载并安装vue.js 第一步:打开Vue2官网&a…

力扣 寻找重复数

二分&#xff0c;双指针&#xff0c;环形链表。 题目 不看完题就是排序后&#xff0c;用两个快慢指针移动&#xff0c;找到相同就返回即可。 class Solution {public int findDuplicate(int[] nums) {Arrays.sort(nums);int l0;int r1;while(r<nums.length){if(nums[l]num…

使用Docker将ros1自定义消息通过rosjava_bootstrap生成jar包

文章目录 预准备环境rosjava_bootstrap坏消息好消息 环境安装docker安装rosjava_bootstrap仓库rosjava_center仓库修改rosjava_bootstrap代码拉取docker镜像放置自己的自定义消息 启动docker编译 预准备环境 rosjava_bootstrap rosjava_bootstrap是将自定义的ROS消息生成java…

分治算法、动态规划、贪心算法、分支限界法和回溯算法的深度对比

1. 分治算法 (Divide and Conquer) 核心思想 分治法三步曲&#xff1a; 分解&#xff08;Divide&#xff09;&#xff1a;将原问题拆分为多个子问题解决&#xff08;Conquer&#xff09;&#xff1a;递归解决子问题合并&#xff08;Combine&#xff09;&#xff1a;合并子问题…

网络安全红队工具

目录 红队及发展趋势 基本概念 发展趋势 防守阶段 备战阶段 临战阶段 实战阶段 战后整顿 如果错过互联网,与你擦肩而过的不仅仅是机会,而是整整一个时代。 红队及发展趋势 基本概念 红队一般指实战攻防的防守方。 红队主要复盘总结现有防护系统的不足之处&#xff0c;为…

ai-2、机器学习之线性回归

机器学习之线性回归 1、机器学习2、线性回归2.1、梯度下降法 3、python下调用scikit-learn 1、机器学习 2、线性回归 ####所以y可以当成我们需要的结果&#xff0c;根据公式可以求的y一撇的值更小&#xff0c;所以更接近需要的结果&#xff0c;所以y一撇拟合性更好 2.1、梯度下…

NO.21十六届蓝桥杯备战|一维数组|范围for|memset|memcpy(C++)

数组是⼀组相同类型元素的集合 数组中存放的是1个或者多个数据&#xff0c;但是数组元素个数不能为0数组中存放的多个数据&#xff0c;类型是相同的 数组分为⼀维数组和多维数组&#xff0c;多维数组⼀般⽐较多⻅的是⼆维数组 一维数组 ⼀维数组是最常⻅的&#xff0c;通常⽤…

unity TextMeshPro动态字体使用

TextMeshPro 显示文本的时候&#xff0c;依赖与文本贴图&#xff0c;这个贴图可以是静态的&#xff0c;也可以根据显示需求动态生成&#xff0c;动态的资源对内存消耗会高一些&#xff0c;所以我们一般将常用的3500汉字创建一个静态的字体库&#xff0c;然后在创建一个动态字体…

爱普生可编程晶振 SG-8101CE 在智能家居领域展现出的优势

在智能家居的全场景应用中&#xff0c;设备间的协同效率、数据传输的稳定性以及系统运行的可靠性&#xff0c;成为衡量用户体验的核心标准。爱普生 SG-8101CE 可编程晶振以其卓越的性能&#xff0c;为智能门锁、传感器、中控系统等设备提供核心动力&#xff0c;助力厂商打造更可…

杰发科技AC7801——滴答定时器获取时间戳

1. 滴答定时器 杰发科技7801内部有一个滴答定时器&#xff0c;该定时器是M0核自带的&#xff0c;因此可以直接用该定时器来获取时间戳。 同样&#xff0c;7803也可以使用该方式获取时间戳。 2. 滴答定时器原理 SysTick是一个24位的递减计数器&#xff0c;它从预设的重装载值…

2021-05-27 C++找出矩阵数组中值最大的元素和它在数组中的位置

缘由各位大佬&#xff0c;这个应该怎么做_编程语言-CSDN问答 void 找出数组中值最大的元素和它在数组中的位置() {//缘由https://ask.csdn.net/questions/7436585?spm1005.2025.3001.5141int a[4][4], aa 0, aaa 0, d 0, x 0;while (aa < 4 && aaa < 4)std…

k8s集群3主5从高可用架构(kubeadm方式安装k8s)

关键步骤说明 环境准备阶段 系统更新&#xff1a;所有节点执行yum/apt update确保软件包最新时间同步&#xff1a;通过ntpdate time.windows.com或部署NTP服务器网络规划&#xff1a;明确划分Service网段&#xff08;默认10.96.0.0/12&#xff09;和Pod网段&#xff08;如Flann…

Android实现漂亮的波纹动画

Android实现漂亮的波纹动画 本文章讲述如何使用二维画布canvas和camera、矩阵实现二、三维波纹动画效果&#xff08;波纹大小变化、画笔透明度变化、画笔粗细变化&#xff09; 一、UI界面 界面主要分为三部分 第一部分&#xff1a;输入框&#xff0c;根据输入x轴、Y轴、Z轴倾…

【无标题】ABP更换MySql数据库

原因&#xff1a;ABP默认使用的数据库是sqlServer&#xff0c;本地没有安装sqlServer&#xff0c;安装的是mysql&#xff0c;需要更换数据库 ABP版本&#xff1a;9.0 此处以官网TodoApp项目为例 打开EntityFrameworkCore程序集&#xff0c;可以看到默认使用的是sqlServer&…

Windows上使用go-ios实现iOS17自动化

前言 在Windows上运行iOS的自动化&#xff0c;tidevice对于iOS17以上并不支持&#xff0c;原因是iOS 17 引入新通信协议 ‌RemoteXPCQUIC‌&#xff0c;改变了 XCUITest 的启动方式。 一、go-ios的安装 1、安装命令&#xff1a;npm i go-ios 2、安装完成后输入命令which io…

Grok3使用体验与模型版本对比分析

文章目录 Grok的功能DeepSearch思考功能绘画功能Grok 3的独特功能 Grok 3的版本和特点与其他AI模型的比较 最新新闻&#xff1a;Grok3被誉为“地球上最聪明的AI” 最近&#xff0c;xAI公司正式发布了Grok3&#xff0c;并宣称其在多项基准测试中展现了惊艳的表现。据官方消息&am…

JavaScript——前端基础3

目录 JavaScript简介 优点 可做的事情 运行 第一个JavaScript程序 搭建开发环境 安装的软件 操作 在浏览器中使用JavaScript文件 分离JS 使用node运行JS文件 语法 变量与常量 原生数据类型 模板字符串 字符串的内置方法 数组 对象 对象数组和JSON if条件语…

视频推拉流EasyDSS点播平台云端录像播放异常问题的排查与解决

EasyDSS视频直播点播平台是一个功能全面的系统&#xff0c;提供视频转码、点播、直播、视频推拉流以及H.265视频播放等一站式服务。该平台与RTMP高清摄像头配合使用&#xff0c;能够接收无人机设备的实时视频流&#xff0c;实现无人机视频推流直播和巡检等多种应用。 最近&…