Spring之循环依赖

什么是循环依赖?

依赖的相互引用,如下列的这种形式

@Component
public class A {@Autowiredprivate B b;}@Component
public class B {@Autowiredprivate A a;
}

Spring是如何解决循环依赖的

Spring是通过三级缓存来解决循环依赖

  • singletonObjects : 单例bean,已经实例化,完成属性填充
  • earlySingletonObjects : 半成品bean,已经实例化,未完成属性填充
  • singletonFactories : 一个函数式接口

为什么要使用三级缓存?

因为Spring的动态代理流程是在属性填充流程之后的,如果只使用二级缓存,半成品bean中不确定是放一个普通对象还是代理对象,所以需要使用三级缓存来保存一个不确定的值

PS : 如果只使用二级缓存,那必须所有对象都进行动态代理,那样会生成很多class文件,浪费内存

图解一般情况下的循环依赖

Spring真的能完全解决循环依赖? 

改造一下上文代码

@Component
public class A {private B b;public A(B b) {this.b = b;}
}@Component
public class B {@Autowiredprivate A a;
}

很遗憾,Spring没能解决这种构造器与setter注入形式的循环依赖,我们来分析具体原因

前置知识点

  1. 如果一个类有且仅有一个有参构造方法,Spring会以此构造方法实例化对象
  2. 实例化对象之前,会先处理参数的依赖。比如上述代码中bean A的创建过程中,会先getBean(b),再实例化对象A

源码分析

AbstractBeanFactory#doGetBean

我们先看一下这个getSingleton方法本身,而不是createBean方法

由上述源码我们可以得知:执行createBean方法之前会将beanName加入到singletonsCurrentlyInCreation列表中,表明这个bean正在创建

后续b进行属性填充的时候会先从singletonFactories中获取a,因为a还没有进行实例化,没有放入singletonFactories中,所以又会执行getSingleton方法,因为singletonsCurrentlyInCreation这个列表已经存在a这个beanName,所以if条件成立,抛出异常

图解流程

构造方法与setter注入的循环依赖,如果构造方法对应的bean先处理,则会抛出异常,后处理则不会抛出异常。

注意 : bean A 还没有实例化,singletonFactories​​中还没有提前暴露的对象

如果将上述代码改下列形式,则不会抛出异常

@Component
public class A {@Autowiredprivate B b;
}@Component
public class B {private A a;public B(A a) {this.a = a;}
}

PS :针对A先实例化,B后实例化 

综上所述

  • setter和setter的循环依赖:正确注入
  • 构造方法和setter的循环依赖:抛出异常
  • setter和构造方法的循环依赖:正确注入
  • 构造方法和构造方法的循环依赖:抛出异常

普通情况下,我们标记bean正在创建,后续会将实例对象提前暴露放入singletonFactories中,但是构造方法和setter方式的循环依赖在标记bean正在创建后,并没有立刻将实例对象放入singletonFactories中,而是处理构造方法中参数所对应的依赖,如果这个参数对应的依赖,循环依赖了当前bean,则会抛出异常。即标记正在创建的bean,在对象提前暴露放入singletonFactories之前,不能注入一个依赖当前bean的bean

Spring如何解决循环依赖?

SpringBoot2.6及以上版本默认不支持循环依赖,那如何解决循环依赖呢?

主要原因就是SpringBoot将allowCircularReferences默认值设置为false

从配置角度

1.在application.properties文件中将该值设置为true

spring.main.allow-circular-references=true

2.使用bfpp将该值设置为true

@Component
public class FirstBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) registry;defaultListableBeanFactory.setAllowCircularReferences(true);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}
从代码角度

1.使用@Lazy注解

@Component
public class A {@Autowired@Lazyprivate B b;}@Component
public class B {@Autowiredprivate A a;}

2.使用@Lookup注解

@Component
public class A {private B b;@Lookuppublic B getB() {return this.b;}
}@Component
public class B {@Autowiredprivate A a;}

3.实现ApplicationContextAware接口

@Component
public class A implements ApplicationContextAware {private B b;private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;this.b = applicationContext.getBean(B.class);}}@Component
public class B {@Autowiredprivate A a;}

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

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

相关文章

牛客2024年愚人节比赛(A-K)

比赛链接 毕竟是娱乐场,放平心态打吧。。。 只有A一个考了数学期望,其他的基本都是acmer特有的脑筋急转弯,看个乐呵即可。 A 我是欧皇,赚到盆满钵满! 思路: 我们有 p 1 p_1 p1​ 的概率直接拿到一件实…

Redis改造原始代码

基础篇Redis 5.2.2.改造原始代码 代码说明: 1.在我们完成了使用工厂设计模式来完成代码的编写之后,我们在获得连接时,就可以通过工厂来获得。 ,而不用直接去new对象,降低耦合,并且使用的还是连接池对象。 2.当我们…

FreeROST作业day2

1.总结串口的发送和接收功能使用到的函数 串口发送数据函数: HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout); UART_Handle…

【LeetCode】热题100:排序链表

题目: 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 示例 1: 输入:head [4,2,1,3] 输出:[1,2,3,4] 示例 2: 输入:head [-1,5,3,4,0] 输出:[-1,0,3,4,5] …

linux进程fork函数的讲解。

通过指令,查看接口的详细信息 man forkOn success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately. 这里的返回值的意…

FPGA设计_加法器

文章目录 前言补充:各种门电路符号一、半加器二、全加器三、串行进位加法器3.1、verilog代码设计 四、超前进位加法器4.1、verilog代码设计 五、进位链CARRY4 前言 在之前一篇介绍7系列FPGA底层资源的时候,我们提到过每一个slice当中有一个CARRY4&#…

玫瑰图和雷达图(自备)

目录 玫瑰图 数据格式 绘图基础 绘图升级(文本调整) 玫瑰图 下载数据data/2020/2020-11-24 mirrors_rfordatascience/tidytuesday - 码云 - 开源中国 (gitee.com) R语言绘图—南丁格尔玫瑰图 - 知乎 (zhihu.com) 数据格式 rm(list ls()) libr…

2024年新算法-冠豪猪优化算法(CPO),CPO-RF-Adaboost,CPO优化随机森林RF-Adaboost回归预测-附代码

冠豪猪优化算法(CPO)是一种基于自然界中猪群觅食行为启发的优化算法。该算法模拟了猪群在寻找食物时的集群行为,通过一系列的迭代过程来优化目标函数,以寻找最优解。在这个算法中,猪被分为几个群体,每个群体…

CA根证书——https安全保障的基石

HTTPS通信中,服务器端使用数字证书来证明自己的身份。客户端需要验证服务器发送的证书的真实性。这就需要一个可信的第三方机构,即CA,来颁发和管理证书。CA根证书是证书颁发机构层次结构的顶级证书,客户端信任的所有证书都可以追溯…

python实现泊松回归

1 什么是基于计数的数据? 基于计数的数据包含以特定速率发生的事件。发生率可能会随着时间的推移或从一次观察到下一次观察而发生变化。以下是基于计数的数据的一些示例: 每小时穿过十字路口的车辆数量每月去看医生的人数每月发现的类地行星数量 计数数…

行车记录打不开?别慌,数据恢复有高招!

行车记录打不开,这恐怕是许多车主都曾经遭遇过的烦恼。在驾驶途中,行车记录仪本应是记录美好瞬间、保障行车安全的重要工具,但一旦它出现打不开的情况,所有的期待与信赖便瞬间化为乌有。面对这种情况,我们该如何应对&a…

web学习笔记(五十一)

目录 1. post请求和get请求的区别 2. CORS 跨域资源共享 2.1 什么是同源 2.2 什么是同源策略 2.3 如何实现跨域资源共享 2.4 使用 cors 中间件解决跨域问题 2.5 JSONP 接口 2.6 实现 JSONP 接口的步骤 1. post请求和get请求的区别 传参方式不同:get请求参数…

文本文件操作

大家好&#xff1a; 衷心希望各位点赞。 您的问题请留在评论区&#xff0c;我会及时回答。 文件操作 程序运行时&#xff0c;产生的数据都是临时数据&#xff0c;程序一旦运行结束都会被释放。通过文件可以将数据持久化。 C中对文件进行操作需要包含头文件<fstream> 文件…

2024年抖音小店的保证金是多少?真的可以做0元保证金的店铺吗?

大家好&#xff0c;我是电商糖果 2024年想要入驻抖音小店的商家依旧很多&#xff0c;关于小店的保证金问题也有不少人前来咨询。 大家问的最多的是可以开通0元保证金的店铺吗&#xff1f;以及2024年抖音小店保证金是多少&#xff1f; 这里糖果给大家一个个解答。 可以开通0…

第十八章 算法

一、介绍 1.1 什么是算法 算法&#xff08;Algorithm&#xff09;是指解题方案的准确而完整的描述&#xff0c;是一系列解决问题的清晰指令&#xff0c;算法代表着用系统的方法描述解决问题的策略机制。也就是说&#xff0c;能够对一定规范的输入&#xff0c;在有限时间内获…

注意力机制篇 | YOLOv8改进之在C2f模块添加级联群体注意力机制CGAttention | CVPR 2023

前言:Hello大家好,我是小哥谈。级联群体注意力机制(Cascading Group Attention)是一种注意力机制,它通过对输入序列进行逐级处理来捕捉不同层次的语义结构。该机制主要由两个关键部分组成:群体注意力和级联过程。在具体实现上,级联群体注意力机制通过构建一个层次结构,…

YOLOv9改进策略 :IoU优化| Inner-IoU基于辅助边框的IoU损失,高效结合 GIoU, DIoU, CIoU,SIoU 等 | 2023.11

💡💡💡本文独家改进:Inner-IoU引入尺度因子 ratio 控制辅助边框的尺度大小用于计算损失,并与现有的基于 IoU ( GIoU, DIoU, CIoU,SIoU )损失进行有效结合,实现高效涨点 💡💡💡适用场景:小目标数据集,涨点近两个点,强烈推荐 《YOLOv9魔术师专栏》将从以下…

第十七章 Kafka

一、特性 - 高吞吐、低延迟 - 高伸缩性 - 持久性、可靠性 - 容错性 - 高并发 通过 O(1)的磁盘数据结构提供消息的持久化&#xff0c;这种结构对于即使数以 TB 的消息存储也能够保持长时间的稳定性能。 高吞吐量&#xff1a;即使是非常普通的硬件 Kafka 也可以支持每秒数百…

内网靶机~~dc-2

一、信息收集 1.端口扫描&#xff1a; nmap -sV -p 1-10000 10.1.1.4 2.CMS识别 3.目录扫描&#xff1a; dirsearch http://10.1.1.4/ 4.FLAG1 似乎让我们用cewl生成密码字典&#xff0c;并爆破登录。 cewl -w rewl_passwd.txt http://dc-2/index.php/flag/ 总结&#xff…

跑腿小程序|基于微信小程序的跑腿平台小程序设计与实现(源码+数据库+文档)

跑腿平台小程序目录 目录 基于微信小程序的跑腿平台小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2、跑腿任务管理 3、任务类型管理 4、公告信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、…