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

Spring 解决bean的循环依赖

Spring循环依赖-博客园

1. 什么是循环依赖

2. 循环依赖能引发什么问题

循环依赖可能引发以下问题:

  • 初始化顺序不确定:循环依赖导致无法确定哪个对象应该先被创建和初始化,从而造成初始化顺序的混乱。这可能导致错误的结果或意外的行为。
  • 死锁和无限递归:当循环依赖中的对象在创建过程中相互等待对方完成创建时,可能会导致死锁或无限递归的情况发生。这将使程序无法继续执行,最终导致系统崩溃或进入无限循环。
  • 难以理解和维护:循环依赖增加了代码的复杂性和耦合度,使得代码难以理解和维护。在一个循环依赖链中,修改一个类可能会影响到其他所有相关的类,增加了代码的脆弱性。
  • 可测试性下降:循环依赖使得各个模块或类之间的责任不清晰,难以进行单独的单元测试或模块拆解。这给软件的测试和调试带来困难,降低了可测试性和可维护性。

3. Spring是怎么处理循环依赖的

为避免循环依赖带来的问题,应尽量避免在设计和实现中出现循环依赖关系。重新考虑系统的架构,采用合适的设计模式、解耦方式和依赖注入机制,可以帮助解决或避免循环依赖带来的问题。

据此我们得到以下结论:

spring容器中原型(Prototype)的场景是不支持循环依赖的,抛出BeanCurrentlyInCreationException异常

其实,Spring容器中单例(singleton)的场景是支持循环依赖的,Spring使用了三级缓存和提前曝光(early exposure)的机制来处理循环依赖问题

  • 第一级缓存(也叫单例池)singletonObjects:存放已经经历了完整生命周期的Bean对象
  • 第二级缓存: earlySingletonObjects,存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整)
  • 第三级缓存: Map<String, ObiectFactory<?>> singletonFactories,存放可以生成Bean的工厂

所谓的三级缓存其实就是spring容器内部用来解决循环依赖问题的三个map

Spring实例Bean的本质

  • 实例化
    • 堆内存中申请一块内存空间
    • 租赁好房子,自己的家具东西还没有搬家进去
  • 初始化属性填充
    • 完成属性的各种赋值
    • 装修、家电家具进场

3大Map和四大方法,总体相关对象
在这里插入图片描述

1.getSingleton:从容器里面获得单例的bean
2.doCreateBean: 没有就创建bean
3.populateBean: 创建完了以后,要填充属性
4.addSingleton: 填充完了以后,再添加到容器进行使用

第一层singletonObjects存放的是已经初始化好了的Bean,
第二层earlySingletonObjects存放的是实例化了,但是未初始化的Bean,
第三层singletonFactories存放的是FactoryBean。假如A类实现了FactoryBean,那么依赖注入的时候不是A类,而是A类产生的Bean
A/B两对象在三级缓存中的迁移说明

  1. A创建过程中需要B,于是A将自己放到三级缓存里面,去实例化B
  2. B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A然后把三级缓存里面的这个A放到二级缓存里面,并删除三级缓存里面的A
  3. B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态) 然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建,并将A自己放到一级缓存里面。

https://blog.csdn.net/weixin_41883161/article/details/139706538

Spring框架通过三级缓存(三级缓存机制)来解决大多数情况下的循环依赖问题。三级缓存机制包括以下三个层次:

  • 单例池(singletonObjects):用于存放完全初始化好的单例Bean。
  • 早期曝光对象池(earlySingletonObjects):用于存放部分初始化完成的单例Bean,通常是通过提前暴露Bean引用来解决循环依赖。
  • 三级缓存(singletonFactories):用于存放Bean工厂,以便在需要时创建Bean实例。
> 4.1 三级缓存机制详解
> 4.1.1 单例池(singletonObjects) 单例池是一个Map,用于存放完全初始化好的单例Bean。当Spring容器创建一个Bean时,会首先检查单例池中是否已经存在该Bean,如果存在则直接返回,否则继续创建。
> 
> 4.1.2 早期曝光对象池(earlySingletonObjects) 早期曝光对象池是一个Map,用于存放部分初始化完成的单例Bean。当Spring容器检测到循环依赖时,会将部分初始化完成的Bean提前放入该池中,以便其他Bean能够引用。
> 
> 4.1.3 三级缓存(singletonFactories) 三级缓存是一个Map,用于存放Bean工厂。Bean工厂是一个用于创建Bean实例的对象,当需要创建Bean实例时,Spring容器会从三级缓存中获取相应的Bean工厂,并通过它来创建Bean实例。

4.2 三级缓存的工作流程

Spring容器创建Bean A,首先检查单例池中是否存在Bean A。
如果单例池中不存在Bean A,则检查早期曝光对象池中是否存在Bean A。
如果早期曝光对象池中也不存在Bean A,则从三级缓存中获取Bean A的工厂,并通过该工厂创建Bean A的实例。
创建Bean A实例的过程中,发现Bean A依赖于Bean B,因此开始创建Bean B。
创建Bean B的过程中,发现Bean B依赖于Bean A,此时检测到循环依赖。
将Bean A的实例放入早期曝光对象池中,以便Bean B可以引用。
继续完成Bean B的创建,并将其放入单例池中。
返回Bean B的实例,继续完成Bean A的创建,并将其放入单例池中。
通过上述流程,Spring容器可以成功处理大多数情况下的循环依赖。

4. Spring怎样注入才能不产生循环依赖问题

相关文章:

Spring 解决bean的循环依赖

Spring循环依赖-博客园 1. 什么是循环依赖 2. 循环依赖能引发什么问题 循环依赖可能引发以下问题&#xff1a; 初始化顺序不确定&#xff1a;循环依赖导致无法确定哪个对象应该先被创建和初始化&#xff0c;从而造成初始化顺序的混乱。这可能导致错误的结果或意外的行为。死…...

鸿蒙内核源码分析(ELF格式篇) | 应用程序入口并不是main

阅读之前的说明 先说明&#xff0c;本篇很长&#xff0c;也很枯燥&#xff0c;若不是绝对的技术偏执狂是看不下去的.将通过一段简单代码去跟踪编译成ELF格式后的内容.看看ELF究竟长了怎样的一副花花肠子&#xff0c;用readelf命令去窥视ELF的全貌&#xff0c;最后用objdump命令…...

seq2seq编码器encoder和解码器decoder详解

编码器 在序列到序列模型中&#xff0c;编码器将输入序列&#xff08;如一个句子&#xff09;转换为一个隐藏状态序列&#xff0c;供解码器生成输出。编码层通常由嵌入层和RNN&#xff08;如GRU/LSTM)等组成 Token:是模型处理文本时的基本单元&#xff0c;可以是词,子词,字符…...

前端使用 Konva 实现可视化设计器(21)- 绘制图形(椭圆)

本章开始补充一些基础的图形绘制&#xff0c;比如绘制&#xff1a;直线、曲线、圆/椭形、矩形。这一章主要分享一下本示例是如何开始绘制一个图形的&#xff0c;并以绘制圆/椭形为实现目标。 请大家动动小手&#xff0c;给我一个免费的 Star 吧~ 大家如果发现了 Bug&#xff0c…...

Python 将单词拆分为单个字母组成的列表对象

Python 将单词拆分为单个字母组成的列表对象 正文 正文 这里介绍一个简单算法&#xff0c;将英文单词拆分为其对应字母组成的列表。 str1 ACG lst1 [i for i in str1] lst2 list(str1)# Method 1 print(lst1) # Method 2 print(lst2) """ result: [A, C, G…...

欧洲 摩纳哥税务知识

摩纳哥是一个位于法国南部的城邦国家&#xff0c;以其豪华的生活环境和宽松的税收政策而闻名。自1869年以来&#xff0c;摩纳哥取消了个人所得税的征收&#xff0c;这使得它成为富裕人士和外籍人士的理想居住地。然而&#xff0c;这并不意味着摩纳哥的税收制度完全不存在。以下…...

域控制器的四大支柱分别是车载以太网、自适应Autosar

域控制器的四大支柱分别是车载以太网、自适应Autosar、高性能处理器和集中式E/E架构。 百度安全验证 。自适应Autosar采用Proxy/Skeleton的通信架构&#xff0c;同时采用中间件SOME/IP...

写给大数据开发:如何优化临时数据查询流程

你是否曾因为频繁的临时数据查询请求而感到烦恼&#xff1f;这些看似简单的任务是否正在蚕食你的宝贵时间&#xff0c;影响你的主要工作&#xff1f;如果是&#xff0c;那么这篇文章正是为你而写。 目录 引言&#xff1a;数据开发者的困境问题剖析&#xff1a;临时数据查询的…...

【MongoDB】Java连接MongoDB

连接URI 连接 URI提供驱动程序用于连接到 MongoDB 部署的指令集。该指令集指示驱动程序应如何连接到 MongoDB&#xff0c;以及在连接时应如何运行。下图解释了示例连接 URI 的各个部分&#xff1a; 连接的URI 主要分为 以下四个部分 第一部分 连接协议 示例中使用的 连接到具有…...

nginx支持的不同事件驱动模型

Nginx 支持的不同事件驱动模型 Nginx 是一款高性能的 Web 和反向代理服务器&#xff0c;它支持多种事件驱动模型来处理网络 I/O 操作。不同的操作系统及其版本支持不同的事件驱动模型&#xff0c;这些模型对于 Nginx 的并发处理能力和性能至关重要。下面详细介绍 Nginx 支持的…...

C++ TinyWebServer项目总结(7. Linux服务器程序规范)

进程 PID 进程的PID&#xff08;Process ID&#xff09;是操作系统中用于唯一标识一个进程的整数值。每个进程在创建时&#xff0c;操作系统都会分配一个唯一的PID&#xff0c;用来区分不同的进程。 PID的特点 唯一性&#xff1a; 在操作系统运行的某一时刻&#xff0c;每个…...

基于STM32单片机设计的秒表时钟计时器仿真系统——程序源码proteus仿真图设计文档演示视频等(文末工程资料下载)

基于STM32单片机设计的秒表时钟计时器仿真系统 演示视频 基于STM32单片机设计的秒表时钟计时器仿真系统 摘要 本设计基于STM32单片机&#xff0c;设计并实现了一个秒表时钟计时器仿真系统。系统通过显示器实时显示当前时间&#xff0c;并通过定时器实现秒表计时功能。显示小时…...

人才流失预测项目

在本项目中&#xff0c;通过数据科学和AI的方法&#xff0c;分析挖掘人力资源流失问题&#xff0c;并基于机器学习构建解决问题的方法&#xff0c;并且&#xff0c;我们通过对AI模型的反向解释&#xff0c;可以深入理解导致人员流失的主要因素&#xff0c;HR部门也可以根据分析…...

BUG——imx6u开发_结构体导致的死机问题(未解决)

简介&#xff1a; 最近在做imx6u的linux下裸机驱动开发&#xff0c;由于是学习的初级阶段&#xff0c;既没有现成的IDE可以使用&#xff0c;也没有GDB等在线调试工具&#xff0c;只能把代码烧写在SD卡上再反复插拔&#xff0c;仅靠卑微的亮灯来判断程序死在哪一步。 至于没有使…...

问答:什么是对称密钥、非对称密钥,http怎样变成https的?

文章目录 对称密钥 vs 非对称密钥HTTP 变成 HTTPS 的过程 对称密钥 vs 非对称密钥 1. 对称密钥加密 定义: 对称密钥加密是一种加密算法&#xff0c;其中加密和解密使用的是同一个密钥。特点: 速度快: 因为只使用一个密钥&#xff0c;所以加密和解密速度较快。密钥分发问题: 双…...

虚拟滚动列表组件ReVirtualList

虚拟滚动列表组件ReVirtualList 组件实现基于 Vue3 Element Plus Typescript&#xff0c;同时引用 vueUse lodash-es tailwindCss (不影响功能&#xff0c;可忽略) 在 ReList 的基础上&#xff0c;增加虚拟列表功能&#xff0c;在固定高度的基础上&#xff0c;可以优化大数…...

稳定、耐用、美观 一探究竟六角头螺钉螺栓如何选择

在机器与技术未被发现的过去&#xff0c;紧固件设计和品质并不稳定。但是&#xff0c;他们已成为当今许多行业无处不在的构成部分。六角头标准件或六角头标准件是紧固件中持续的头部设计之一&#xff0c;它有六个面&#xff0c;对广泛工业应用大有益处。六角头标准件或常分成六…...

数据库Mybatis基础操作

目录 基础操作 删除 预编译SQL 增、改、查 自动封装 基础操作 环境准备 删除 根据主键动态删除数据&#xff1a;使用了mybatis中的参数占位符#{ }&#xff0c;里面是传进去的参数。 单元测试&#xff1a; 另外&#xff0c;这个方法是有返回值的&#xff0c;返回这次操作…...

人物形象设计:塑造独特角色的指南

引言 人物形象设计是一种创意过程&#xff0c;它利用强大的设计工具&#xff0c;通过视觉和叙述元素塑造角色的外在特征和内在性格。这种设计不仅赋予角色以生命&#xff0c;还帮助观众或读者在心理层面上与角色建立联系。人物形象设计的重要性在于它能够增强故事的吸引力和说…...

网络安全-安全策略初认识

文章目录 前言理论介绍1. 安全策略1.1 定义&#xff1a;1.2 关键术语&#xff1a; 2. 防火墙状态监测 实战步骤1&#xff1a;实验环境搭建步骤2&#xff1a;配置实现 总结1. 默认安全策略2. 自定义安全策略3. 防火墙状态会话表 前言 who&#xff1a;本文主要写给入门防火墙的技…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...