spring循环依赖

Spring 通过三级缓存机制解决单例 Bean 的循环依赖问题,其核心思想是提前暴露未完全初始化的 Bean 引用。以下是详细流程和原理:


1. 循环依赖的场景

假设两个 Bean 相互依赖:

  • BeanA 依赖 BeanB
  • BeanB 依赖 BeanA

如果没有特殊处理,Spring 会在创建 BeanA 时发现需要 BeanB,而创建 BeanB 时又需要 BeanA,导致死循环。


2. 三级缓存的作用

Spring 使用三个 Map(缓存)管理 Bean 的中间状态:

  1. 一级缓存 singletonObjects
    存放完全初始化好的单例 Bean,可直接使用。
  2. 二级缓存 earlySingletonObjects
    存放早期暴露的 Bean 对象(已实例化但未完成属性填充和初始化)。
  3. 三级缓存 singletonFactories
    存放 Bean 工厂对象ObjectFactory),用于生成早期 Bean 的引用(可能包含代理对象)。

3. 解决循环依赖的流程

BeanABeanB 相互依赖为例:

步骤 1:创建 BeanA
  1. 实例化 BeanA
    调用构造函数创建 BeanA 的实例(此时属性未填充)。
  2. 暴露早期引用
    BeanA 的工厂对象(ObjectFactory)放入三级缓存
  3. 填充属性 BeanB
    Spring 发现 BeanA 依赖 BeanB,触发 BeanB 的创建。
步骤 2:创建 BeanB
  1. 实例化 BeanB
    调用构造函数创建 BeanB 的实例。
  2. 暴露早期引用
    BeanB 的工厂对象放入三级缓存
  3. 填充属性 BeanA
    Spring 发现 BeanB 依赖 BeanA,尝试从缓存中获取 BeanA
    • 一级缓存:无。
    • 二级缓存:无。
    • 三级缓存:找到 BeanA 的工厂对象,调用 getObject() 生成早期引用,并将 BeanA 移至二级缓存
  4. 完成 BeanB 的初始化
    BeanB 的完整对象放入一级缓存
步骤 3:回到 BeanA 的初始化
  1. 获取 BeanB 实例
    BeanA 通过已初始化的 BeanB 完成属性注入。
  2. 完成 BeanA 的初始化
    BeanA 放入一级缓存,并从二级缓存中移除。

4. 关键设计点

为什么需要三级缓存?
  • 分离职责
    三级缓存通过 ObjectFactory 延迟生成 Bean 的早期引用,确保 AOP 代理仅在需要时创建(例如,若 BeanA 需要代理,工厂会返回代理对象,避免重复创建)。
  • 避免重复代理
    如果只有二级缓存,可能在多个地方重复生成代理对象,破坏单例。
为何构造函数注入无法解决循环依赖?
  • 实例化前无法暴露引用
    构造函数注入发生在实例化阶段,此时 Bean 尚未创建,无法提前暴露引用到三级缓存,导致 Spring 抛出 BeanCurrentlyInCreationException

5. 限制条件

  1. 仅支持单例 Bean
    原型(Prototype)作用域的 Bean 每次创建新对象,无法通过缓存解决循环依赖。
  2. 依赖的注入方式必须为 Setter 或字段注入
    构造函数注入无法解决循环依赖。

6. 总结

Spring 通过三级缓存提前暴露未初始化的 Bean 引用,结合延迟代理生成,解决了单例 Bean 的循环依赖问题。其核心是空间换时间,在保证单例和 AOP 一致性的前提下,避免死循环。理解这一机制有助于在开发中避免循环依赖陷阱,或在必要时调整依赖注入方式。

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

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

相关文章

uniapp自身bug | uniapp+vue3打包后 index.html无法直接运行

前提: 已经修改了基础路径 打开打包文件,双击运行index.html报错,无法访问页面 uniappvue2项目是可以正常运行的 vue3修改publicPath: ./后,也是可以正常访问打包文件中的index.html 点进控制台提供的链接:https:/…

Ubuntu快速安装使用gRPC C++

目录 引言一、快速安装1. 安装必要依赖库2. 安装gRPC 二、测试使用三、参考博客 引言 关于gRPC随着云原生微服务的火热也流行了起来,而且学好一个gRPC框架对目前来说也是必须的了。然而对于一个基础的小白来说,这个gRPC的框架运用起来是及其的困难&…

AES 简介 以及 C# 和 js 实现【加密知多少系列_3】

〇、AES 简介 AES 的全称是 Advanced Encryption Standard,意思是高级加密标准。它的出现主要是为了取代 DES(Data Encryption StandardData Encryption Standard)加密算法的,因为我们都知道 DES 算法的密钥长度是 56Bit&#xf…

在Django模型中的Mysql安装

安装mysql驱动 文章目录 安装mysql驱动1.打开PowerShell 安装mysql的驱动2.安装mysqlclient驱动2.1开始安装2.2 pip list 进行验证 出现mysqlclient 以及pymysql即可 3.正式安装mysql3.1打开mysql官网 www.mysql.com3.2点击下载 然后划到最后点击mysql社区下载 3.3 点击适合win…

AI赋能企业协作6-FizEIM的功能探索

本系列文章AI赋能企业协作与第一个系列IM工具对比中反复比较了国内外、商业、开源的IM工具以及IM工具的AI支持,在之前的比较对象中,由于信息偏差,Workplus(BeeWorks)已不再开源,这里向各位读者致歉&#xf…

java项目之基于ssm的旅游论坛(源码+文档)

项目简介 旅游论坛实现了以下功能: 用户信息管理: 用户信息新增 用户信息修改 景点信息管理: 景点信息添加 景点信息删除 景点信息修改 论坛类型管理 论坛类型添加 论坛类型修改 论坛类型删除 公告类型管理: 公告类型添加 公…

Linux安装Elasticsearch集群-----docker安装es集群

目录 技术背景 1.2 实验目标 二、实验内容 1.1 服务器规划 二、传统方式安装Elasticsearch集群 2.1 安装Java环境(10.1.1.6/8) 2.3 配置集群节点(以10.1.1.6) 2.4 启动服务 ES Data节点1(10.1.1.8)…

【嵌入式】复刻SQFMI开源的Watchy墨水屏电子表——(2)软件部分

书接上文 基于乐鑫 ESP32-PICO-D4 模块的墨水屏智能手表开源项目Watchy 完成了硬件部分,接下来就是软件部分: 一 开发环境配置(Arduino ESP32) 首先需要进行 Arduino ESP32 开发环境的安装配置,过程参考之前的帖子&a…

关于微信小程序端base64解码问题

由于atob是浏览器端的,对于微信小程序不支持,导致模拟器【开发工具】显示正常,但真机异常解析失败问题,微信小程序原有的api,官方文档中也废弃了 解决方案: 调用: const decodedString ba…

如何通过Odoo 18创建与配置服务器操作

如何通过Odoo 18创建与配置服务器操作 服务器操作是Odoo实现业务流程自动化的核心工具,允许你在服务器端执行自动化任务,通常由按钮点击或自动化工作流等事件触发。这些操作使用 Python 编写,能够执行复杂的业务逻辑,从而增强 Od…

Windows主机、虚拟机Ubuntu、开发板,三者之间文件互传

以下内容源于日常学习的整理,欢迎交流。 下图是Windows主机、虚拟机Ubuntu、开发者三者之间文件互传的方式示意图: 注意,下面谈及的所有方式,都要求两者的IP地址处于同一网段,涉及到的软件资源见felm。 一、Windows主…

[设计模式与源码]1_Spring三级缓存中的单例模式

欢迎来到啾啾的博客🐱,一个致力于构建完善的Java程序员知识体系的博客📚,记录学习的点滴,分享工作的思考、实用的技巧,偶尔分享一些杂谈💬。 欢迎评论交流,感谢您的阅读&#x1f604…

微服务架构中的API网关:Spring Cloud与Kong/Traefik等方案对比

微服务架构中的API网关:Spring Cloud与Kong/Traefik等方案对比 一、API 网关的概念二、API 网关的主要功能2.1 统一入口与路由转发2.2 安全与权限控制2.3 流量管理与容错2.4 API 管理与聚合2.5 监控与日志2.5 协议转换与适配2.6 控制平面与配置管理 三、API 网关选型…

中兴B860AV3.2-T/B860AV3.1-T2_S905L3-B_2+8G_安卓9.0_先线刷+后卡刷固件-完美修复反复重启瑕疵

中兴电信B860AV3.2-T/B860AV3.1-T2_晶晨S905L3-B芯片_28G_安卓9.0_先线刷后卡刷-刷机固件包,完美修复刷机后盒子反复重启的瑕疵。 这两款盒子是可以通刷的,最早这个固件之前论坛本人以及其他水友都有分享交流过不少的固件,大概都…

Stable Diffusion lora训练(一)

一、不同维度的LoRA训练步数建议 2D风格训练 数据规模:建议20-50张高质量图片(分辨率≥10241024),覆盖多角度、多表情的平面风格。步数范围:总步数控制在1000-2000步,公式为 总步数 Repeat Image Epoch …

Web3 时代数据保护的关键挑战与应对策略

Web3 时代数据保护的关键挑战与应对策略 随着互联网技术的飞速发展,我们正步入 Web3 时代,这是一个以去中心化、用户主权和数据隐私为核心的新时代。在这个时代,数据保护成为了一个至关重要的议题。本文将探讨 Web3 时代数据保护面临的主要挑…

微信小程序计算属性与监听器:miniprogram-computed

小程序框架没有提供计算属性相关的 api ,但是官方为开发者提供了拓展工具库 miniprogram-computed。 该工具库提供了两个功能: 计算属性 computed监听器 watch 一、安装 miniprogram-computed 在项目的根目录下,使用如下命令,…

实体机安装linux视频教程。windows和ubuntu共存。启动时选择切换引导系统。

登录ubuntu官网下载iso镜像。 https://ubuntu.com/download 桌面版带G U I 操作界面,服务版靠远程命令行操作,类似wsl,没有图形界面,显卡跑满无需分散算力到显示交互界面上。 点alter natice downloads可以下载旧版本。具体版本选…

Numpy

一、Numpy优势 学习目标 目标 了解Numpy运算速度上的优势 知道Numpy的数组内存块风格 知道Numpy的并行化运算 1 Numpy介绍 Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。 Numpy支持常见的数组和矩…

小红书不绑定手机号会显示ip吗

小红书作为一个生活方式分享平台,拥有庞大的用户群体。在小红书上,用户可以分享自己的生活点滴、购物心得、美食体验等,与其他用户进行互动交流。最近,不少用户对于小红书是否会在不绑定手机号的情况下显示IP属地产生了疑问&#…