Spring之循环依赖

news2025/1/25 4:45:38

什么事循环依赖

很简单的定义就是就如有两个对象A类,B类,其中两个类中的属性都有对方。

A类

public class A{
	private B b;
	}

B类

public class B{
private A a;
}

在Spring中,什么情况下会出现循环依赖

如果要了解循环依赖,首先需要知道Spring中Bean的生命周期。

Bean的生命周期:

  1. Spring扫描class文件获取得到BeanDefinition;
  2. 根据得到的BeanDefinition去生成Bean。
  3. 根据推断构造方法得到实例化的构造方法。
  4. 根据得到的构造方法去实例化一个对象。
  5. 根据得到的对象填充属性(也叫做依赖注入)。
  6. 如果对象中的某个方法被AOP了,则需要为该对象生成一个代理对象。
  7. 最终把代理对象放入单例池中。

根据文章开头提到的的循环依赖,当A对象实例化出来得到一个对象,需要开始对B属性进行赋值,如果发现单例池中没有B对象,则需要开始创建B对象。而在创建完B对象填充A属性的时候,发现A对象也不在单例池中,这个时候就出现了循环依赖。
根据这种情况,Spring为了解决这种问题,提出来了一种机制,这种机制就是三级缓存。

三级缓存:

三级缓存分别是指:
1级缓存:singletonObjects: 缓存的是已经经历过完成Bean的生命周期的Bean对象。
2级缓存: earltSingletonObjects;相比singletonObjects中的Bean,表示缓存的是早期的Bean对象,并没有走完完整的Bean的生命周期。
3级缓存: singletonFactories; 缓存的是ObjectFactory,表示对象工厂,用来创建早期Bean对象的工厂。

如何解决循环依赖

为什么会发生循环依赖
在这里插入图片描述
在A对象创建时,需要B属性,而B属性在单例池中不存在,需要去创建B对象,在填充B对象的属性时,发现需要A对象,而A对象同样不在单例池中。此时就发生了以上的情况。

Spring如何解决这种情况呢?
在这里插入图片描述
A对象在创建B的过程中,在进行依赖注入之前,先把刚实例化出来的对象放入缓存中,再进行依赖注入。此时A依赖了B对象,发现B对象不存在,则需要把B对象创建出来,而B对象创建的过程和A对象一样,也是先实例化出来一个对象放入缓存中,然后开始B对象的依赖注入,此时B对象需要A属性就可以从缓存中获取到,B对象就可以完整走完Bean的生命周期,同时A对象也可以完整走完。

通过以上流程分析,只需要加入一个缓存就可以解决Spring的循环依赖问题,为什么还需要第三个缓存个呢?

加入A对象中有某个方法被AOP了呢?此时在A对象初始化后需要生成一个代理对象。而我们通过以上分析给B赋值的是A对象的原始对象,并非一个代理对象,这就出现了问题,为了解决这种问题,Spring引入了第三个缓存,ObjectFactories。

正常情况下:
1、实例化A对象;
2、A对象属性填充;
3、基于AOP生成一个代理对象;
4、把代理对象放入单例池singletonObjects中。

为了保证放入单例池的代理对象和B对象的A属性是同一个对象,就是需要利用第三级缓存singletonFactories.
1、在实例化出来A对象后,会构造出来一个ObjectFactory对象放入singletonFatories。
在这里插入图片描述
而这个ObjectFactory是一个函数式接口。
在这里插入图片描述
该方法会执行SmartInstantiationAwareBeanPostProcessor中的getEarlyBeanRefrece方法,这个方法首先得到一个缓存key,缓存key就是beanname, 然后把beanName和Bean存储earlyRefreces中,调用wraplfNecessary进行AOP,得到一个代理对象。

有了singletonFactories之后,当实例化完成A对象后,会把A对象包装成一个ObjectFactory,存入singletonFactories中,开始填充B属性,实例化B对象之后,填充A属性,首先从单例池中尝试获取,没有的话尝试从二级缓存中获取,如果还是没有,则真正开始执行三级缓存中缓存的ObjectFactory,将得到的对象存入二级缓存中,同时删除三级缓存中的对象。此时A对象和B对象都可以完成创建,同时是否需要进行AOP交由Spring来决定。
在这里插入图片描述

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

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

相关文章

基于matlab进行雷达信号模拟

一、前言此示例说明如何将基本工具箱工作流应用于以下方案:假设有一个工作频率为 4 GHz 的各向同性天线。假设天线位于全局坐标系的原点。有一个目标,其非波动雷达横截面为0.5平方米,最初位于(7000,5000,0&…

Linux下使用ClamAV病毒查杀

一、介绍Clam AntiVirus 是一款 UNIX 下开源的 (GPL) 反病毒工具包,专为邮件网关上的电子邮件扫描而设计。该工具包提供了包含灵活且可伸缩的监控程序、命令行扫描程序以及用于自动更新数据库的高级工具在内的大量实用程序。该工具包的核心在于可用于各类场合的反病…

CompletableFuture使用详解(IT枫斗者)

CompletableFuture使用详解 简介 概述 CompletableFuture是对Future的扩展和增强。CompletableFuture实现了Future接口,并在此基础上进行了丰富的扩展,完美弥补了Future的局限性,同时CompletableFuture实现了对任务编排的能力。借助这项能力…

2023最新快速单机创建三主三从Redis集群

单机搭建Redis集群 本次采用Redis的5.0.14版本在单机centos8上搭建Redis三主三从集群. 1.创建6个文件夹 一个文件夹代表一个节点,同时也代表每个节点的端口号. 2.下载Redis文件并解压 使用命令: #下载Redis 可以将5.0.14替换成自己想要的版本 wget http://download.redis…

JavaScript面向对象编程再讲

JavaScript面向对象编程再讲 JavaScript支持的面向对象比较复杂,和其他编程语言又有其独特之处。本文是对以前博文 JavaScript的面向对象编程 https://blog.csdn.net/cnds123/article/details/109763357 补充。 概述 这部分是JavaScript面向对象的概括&#xff0c…

计算机网络微课堂1-3节

目录 1. TCP/TP协议​编辑 2. 3.调制解调器 4.因特网的组成 5.电路交换 6.分组交换 重要常用 7.报文交换 8.总结电路交换 报文交换和分组交换 9. 1. TCP/TP协议 2. ISP 网络提供商 ISP的三层 国际 国家 和本地 3.调制解调器 什么是调制解调器,它存在的…

稳压二极管工作原理、重要参数意义和典型电路参数计算

稳压二极管的工作原理:稳压二极管也叫稳压管,它在电路中一般起到稳定电压的作用,也可以为电路提供基准电压值。稳压二极管使用特殊工艺制造,这种工艺使它在反向击穿时仍然可以长时间稳定工作,不损坏,而工作…

macbook触摸板怎么按右键

苹果MacBook电脑触摸板如何右键,对于初次使用MacBook电脑的朋友,是一个小难题,其实MacBook电脑右键打开快捷辅助菜单的方法很简单。我们在MacBook电脑的【系统设置】—【触控板】中对触控板进行设置后可使用不同方式实现鼠标右键。 方法一&am…

形式与语言与自动机总结-----图灵机

图灵机的设计 图灵机的组成: 图灵机包括三部分:输入输出表带 ,上面包括一些空格和输入字符,读写头可以向两个方向移动,每一次可以读取一个字符并对他进行改写,改变状态根据状态转移函数来确定。 状态转移函数: 图灵机…

【树】你真的会二叉树了嘛? --二叉树LeetCode专题Ⅳ

Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…

C# 文件操作

一 File\FileInfo类 在.NETFramework提供的文件操作类基本上都位于System.IO的命名空间下。操作硬盘文件常用的有两个类File\FileInfo. File类主要是通过静态方法实现的,FileInfo类是通过实例方法。 File类核心成员: FileInfo类的实例成员提供了与Fil…

Redis实现分布式锁的7种方案,及正确使用姿势!

redis学习笔记 7种方案前言 日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁。而Redis非常适合作为分布式锁使用。本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式。如果有不正确的地方,欢迎大家指出…

c盘如何扩展分区?C盘满了这么处理就对了

案例分享:“c盘如何扩展分区?我的电脑C盘前几天都还有50GB,这几天发现越来越小了,电脑也越来越卡顿了,为什么我的C盘突然就满了呢?那么我该怎么解决这个问题?请求大神的帮助!” 在使…

C++内存管理详解

大家好,这里是bang_bang,今天来分享下内存管理的知识。 目录 1.C/C内存分布 2.C内存管理方式 2.1new/delete操作内置类型 2.2new/delete操作自定义类型 3.operator new与operator delete函数 3.1operator new 3.2operator delete 4.new和delete的实现…

【C++进阶之路】初始C++语法(上)

文章目录前言一.命名空间命名冲突命名空间的使用展开命名空间作用域限定符访问作用域命名空间的合并命名空间的嵌套二.输入输出打印流插入运算符输入流提取运算符三.缺省参数全缺省半缺省跨文件缺省函数参数缺省参数的使用格式四.函数重载参数个数不同参数类型不同参数顺序不同…

ubuntu20 qt6.4.3 ustc镜像安装 xdma

文件下载地质 命令 ./qt-unified-linux-x64-4.5.2-online.run --mirror https://mirrors.ustc.edu.cn/qtproject没有镜像就下砸错误hash verification while downloading,this is temporary error,please retry 部分安装器不支持 --mirror cd ~/workspace/dma_ip_drivers/X…

RCIE练习题2之BGP4+配置

R4-R10共7台设备,运行BGP 4+路由协议,其中R4和R5、R6之间为EBGP邻居,其余设备之间为IBGP邻居,将R4 loopback 0的IPv6地址通过重分发方式引入BGP 4+,不得引入多余路由,在R5-R10上均可学习到R4的loopback 0 IPv6地址,同时通过合适配置使得R4上能够学习到R5-R10的loopback …

Excel技能之数据验证,总有一款适合你

用户填写的内容,是未知的,不可靠的。但是,我们要对数据的规范、格式、条件做出限制,既能保证数据的质量,也能统一每个人的行为。最大限度去避免垃圾数据的录入,眼不见心不烦,让心情美美的。 数…

Cont. DB Project ----- MySQL Python Project

Function achieve (Cont.) Item Search 添加一个新函数search_item,用于实现商品搜索的功能。参数:keyword (为了模糊查询) # search items by keywords def search_item(keyword):cursor, db connect_database()sql f"SE…

milovski-V-XXXXXX勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

目录 前言: 一、勒索病毒milovski-V-XXXXXXXX的危害 二、milovski-V-XXXXXXXX勒索病毒的数据恢复方法 三、milovski-V-XXXXXXXX勒索病毒加密数据恢复案例 四、如何防范勒索病毒攻击 前言: 在当今互联网时代,勒索病毒已成为企业信息安全面…