Spring 三级缓存 vs 二级缓存:深度解析循环依赖的终极解决方案

目录

一. 循环依赖的本质矛盾

1. 什么是循环依赖?

2. 矛盾的核心

二.  三级缓存架构解析

三级缓存工作流程图​编辑

三、为什么必须三级缓存?

1. 二级缓存的致命缺陷

2. 三级缓存的精妙设计

四、场景推演:三级缓存如何解决代理问题

1. 正常流程(无循环依赖)

2. 循环依赖流程 ​编辑

五、源码级验证

1. 三级缓存获取逻辑

 2. 代理对象生成点

六、如果强行使用二级缓存

在 Spring 框架中,循环依赖(Circular Dependency)是开发过程中最常见的陷阱之一。Spring 通过三级缓存机制优雅地解决了这一问题,但许多开发者会疑惑:为什么需要三级缓存?二级缓存能否实现同样的效果?本文将通过源码分析、场景推演和设计哲学,揭示这一机制背后的精妙设计。


一. 循环依赖的本质矛盾

1. 什么是循环依赖?

当两个或多个 Bean 相互依赖时,就会形成循环依赖:

// Bean A 依赖 Bean B
@Component
public class A {@Autowiredprivate B b;
}// Bean B 依赖 Bean A
@Component
public class B {@Autowiredprivate A a;
}

2. 矛盾的核心

  • 构造器注入无法解决循环依赖:必须通过 Setter 或字段注入。

  • Bean 创建的生命周期冲突

二.  三级缓存架构解析

Spring 通过三级缓存解决循环依赖问题,其核心数据结构如下:

缓存级别数据结构存储内容
一级缓存singletonObjects完全初始化完成的单例 Bean
二级缓存earlySingletonObjects提前暴露的早期 Bean(未完成属性注入)
三级缓存singletonFactoriesBean 的 ObjectFactory(用于生成代理对象)

三级缓存工作流程图

三、为什么必须三级缓存?

1. 二级缓存的致命缺陷

假设只有一级缓存 + 二级缓存

  • 场景:Bean A 依赖 Bean B,Bean B 依赖 Bean A,且 A 需要 AOP 代理

  • 问题链

    1. A 实例化后放入二级缓存(原始对象)

    2. B 从二级缓存获取 A 的原始对象并注入

    3. A 完成初始化后需要生成代理对象

    4. 结果:B 中持有的是 A 的原始对象,与最终代理对象不一致

2. 三级缓存的精妙设计

通过 ObjectFactory 延迟处理代理:

// AbstractAutowireCapableBeanFactory
protected Object getEarlyBeanReference(String beanName, Object bean) {// 通过后置处理器生成代理对象return applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
  • 动态决策:只有在发生循环依赖时才会调用 ObjectFactory

  • 代理一致性:保证所有依赖方拿到的是同一个代理对象


四、场景推演:三级缓存如何解决代理问题

1. 正常流程(无循环依赖)

2. 循环依赖流程 

五、源码级验证

1. 三级缓存获取逻辑

// DefaultSingletonBeanRegistry
protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;
}

 2. 代理对象生成点

// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(...) {// 1. 实例化对象instanceWrapper = createBeanInstance(beanName, mbd, args);// 2. 加入三级缓存addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));// 3. 属性填充(可能触发循环依赖)populateBean(beanName, mbd, instanceWrapper);// 4. 初始化(生成最终代理对象)exposedObject = initializeBean(beanName, exposedObject, mbd);
}

六、如果强行使用二级缓存?

假设合并三级缓存中的 singletonFactories 和 earlySingletonObjects,会导致:

  1. 提前暴露未完成对象:可能将半成品 Bean 暴露给其他线程

  2. 代理对象不一致:普通 Bean 与代理 Bean 可能同时存在

  3. 内存泄漏风险:无法及时清理创建失败的 Bean 引用

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

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

相关文章

视频流畅播放相关因素

视频播放的流畅度是一个综合性问题&#xff0c;涉及从视频文件本身到硬件性能、网络环境、软件优化等多个环节。以下是影响流畅度的关键因素及优化建议&#xff1a; 一、视频文件本身 1. 分辨率与帧率 1.问题&#xff1a;高分辨率&#xff08;如4K&#xff09;或高帧率&#…

金融项目实战

测试流程 测试流程 功能测试流程 功能测试流程 需求评审制定测试计划编写测试用例和评审用例执行缺陷管理测试报告 接口测试流程 接口测试流程 需求评审制定测试计划分析api文档编写测试用例搭建测试环境编写脚本执行脚本缺陷管理测试报告 测试步骤 测试步骤 需求评审 需求评…

LeetCode 25 - K 个一组翻转链表

LeetCode 25 - K 个一组翻转链表 这道题是一个典型的链表操作题&#xff0c;考察我们对链表的精确操作&#xff0c;包括反转链表、分组处理、递归和迭代的结合应用等。还可以通过变体问题延伸到优先队列操作、归并、分块等&#xff0c;这使得它成为面试中的高频考题之一。 题目…

Leetcode 54: 螺旋矩阵

Leetcode 54: 螺旋矩阵 是一道经典的矩阵遍历模拟题目&#xff0c;要求我们以螺旋顺序遍历一个二维数组。这个问题在面试中非常经典&#xff0c;考察模拟、数组操作以及逻辑清晰度。掌握本题的高效解法可以迅速给面试官留下好印象。 适合面试的解法&#xff1a;边界法&#xff…

abseil-cpp:环境搭建

参考: https://abseil.io/docs/cpp/quickstart-cmake abseil-cpp.git/dd4c89b abseil-cpp.git/20240722.1 1. clone代码仓库、编译 git clone https://github.com/abseil/abseil-cpp.git /app/abseil-cpp/ #/app/abseil-cpp/.git/config git checkout 20240722.1git rev-pa…

Storm实时流式计算系统(全解)——下

storm编程案例-网站访问来源实时统计-需求 storm编程-网站访问来源实时统计-代码实现 根据以上条件可以只写一个类&#xff0c;我们只需要写2个方法和一个main&#xff08;&#xff09;&#xff0c;一个读取/发射&#xff08;spout&#xff09;。 一个拿到数据统计后发到redis…

什么是SYN洪范攻击?

文章目录 一、什么是SYN洪范攻击&#xff1f;二、SYN泛洪攻击原理2.1 TCP 三次握手过程2.2 SYN攻击过程 三、防御措施 一、什么是SYN洪范攻击&#xff1f; SYN洪泛攻击&#xff08;SYN Flood&#xff09;发生在OSI第四层&#xff0c;是一种基于‌TCP协议三次握手漏洞‌的DoS&a…

【嵌入式】MQTT

MQTT 文章目录 MQTT安装简介MQTT客户端代码 安装 安装Paho MQTT C库: sudo apt-get install libpaho-mqtt3-dev头文件包含&#xff1a; #include "MQTTClient.h"编译选项&#xff1a; gcc -o $ $^ -lpaho-mqtt3c简介 MQTT协议全称是&#xff08;Message Queuing…

ubuntu离线安装nvidia-container-runtime

参考文章 ubuntu系统docker20.4版本安装nvidia-container-runtime3.11.0-1版本(离线安装nvidia-docker) - jokerMM - 博客园 https://zhuanlan.zhihu.com/p/15194336245 一、软件地址 Index of /nvidia-docker/libnvidia-container/stable/ 从上述地地址——进入对应系统—…

用Python+Flask打造可视化武侠人物关系图生成器:从零到一的实战全记录

用PythonFlask打造可视化武侠人物关系图生成器&#xff1a;从零到一的实战全记录 一、缘起&#xff1a;一个程序小白的奇妙探索之旅 作为一个接触Python仅13天的编程萌新&#xff0c;我曾以为开发一个完整的应用是遥不可及的事情。但在DeepSeek的帮助下&#xff0c;我竟用短短…

RPA 职业前景:个人职场发展的 “新机遇”

1. RPA职业定义与范畴 1.1 RPA核心概念 机器人流程自动化&#xff08;RPA&#xff09;是一种通过软件机器人模拟人类操作&#xff0c;自动执行重复性、规则性任务的技术。RPA的核心在于其能够高效、准确地处理大量数据和流程&#xff0c;减少人工干预&#xff0c;从而提高工作…

Full GC 排查

在 Java 中&#xff0c;Full GC&#xff08;完全垃圾回收&#xff09;会对整个堆&#xff08;包括年轻代和老年代&#xff0c;甚至可能包括永久代/元空间&#xff09;进行垃圾回收&#xff0c;通常会导致较长的停顿&#xff08;STW&#xff0c;Stop-The-World&#xff09;。如果…

go语言中字符串嵌套

在Go语言中&#xff0c;字符串嵌套通常是指在字符串中包含另一个字符串。可以通过以下几种方式实现&#xff1a; 1. 使用双引号和转义字符 如果需要在字符串中嵌套双引号&#xff0c;可以使用转义字符 \ 来表示内部的双引号。例如&#xff1a; s : "He said, \"He…

Docker 学习(二)——基于Registry、Harbor搭建私有仓库

Docker仓库是集中存储和管理Docker镜像的平台&#xff0c;支持镜像的上传、下载、版本管理等功能。 一、Docker仓库分类 1.公有仓库 Docker Hub&#xff1a;官方默认公共仓库&#xff0c;提供超过10万镜像&#xff0c;支持用户上传和管理镜像。 第三方平台&#xff1a;如阿里…

js的简单介绍

一.javascript&#xff08;是什么&#xff09; 是一种运行在客户端(浏览器)的编程语言&#xff0c;实现人机交互效果 作用 网页特效&#xff08;监听客户的一些行为让网页做出对应的反馈&#xff09;表单验证(针对表格数据的合法性进行判断)数据交互(获取后台的数据&#xf…

k8s架构及服务详解

目录 1.1.容器是什么1.2.Namespace1.3.rootfs5.1.Service介绍5.1.1.Serice简介 5.1.1.1什么是Service5.1.1.2.Service的创建5.1.1.3.检测服务5.1.1.4.在运行的容器中远程执行命令 5.2.连接集群外部的服务 5.2.1.介绍服务endpoint5.2.2.手动配置服务的endpoint5.2.3.为外部服务…

01. HarmonyOS应用开发实践与技术解析

文章目录 前言项目概述HarmonyOS应用架构项目结构Ability生命周期 ArkTS语言特性装饰器状态管理 UI组件与布局基础组件响应式布局样式与主题 页面路由与参数传递页面跳转参数接收 数据绑定与循环渲染数据接口定义循环渲染 条件渲染组件生命周期最佳实践与性能优化组件复用响应式…

【虚拟机 IP 配置深度剖析】

虚拟机 IP 配置深度剖析 在虚拟机的使用过程中&#xff0c;IP 配置犹如搭建房屋的基石&#xff0c;是确保虚拟机与外部网络顺畅通信、与其他设备高效交互的关键所在。本文将以 CentOS 虚拟机为例&#xff0c;深入解读 IP 配置的奥秘。 一、认识网络模式 • NAT 模式&#xf…

【Python 数据结构 5.栈】

目录 一、栈的基本概念 1.栈的概念 2.入栈 入栈的步骤 3.出栈 出栈的步骤 4.获取栈顶元素 获取栈顶元素的步骤 二、 Python中的栈 顺序表实现 链表实现 三、栈的实战 1.LCR 123. 图书整理 I 思路与算法 2.LCR 027. 回文链表 思路与算法 3.1614. 括号的最大嵌套深度 思路与算法 …

Machine Learning 初探

前置知识 pandas 读取文件&#xff1a;read_csv查看信息 describe&#xff1a;查看整体信息&#xff0c;包括每列的平均值、最大最小值、标准差等head&#xff1a;输出头部几行数据columns&#xff1a;输出所有列名loc&#xff1a;查询数据&#xff0c;或是根据索引取对应的数…