详细解释一下Spring是如何解决循环依赖问题的
Spring是如何解决循环依赖问题的?
我们都知道,如果在代码中,将两个或多个Bean互相之间持有对方的引用就会发生循环依赖。循环的依赖将会导致注入死循环,这是Spring发生循环依赖的原因
循环依赖有三种形态
1.互相依赖:
A依赖B , B依赖A , 他们之间形成了循环依赖

2.间接依赖:
A依赖B ,B依赖C , C又依赖A,形成了循环依赖

3.自我依赖:
A依赖A形成了循环依赖

Spring中的三级缓存
Spring中设计了三级缓存来解决循环依赖问题,当我们去调用getBean()方法的时候:
1> Spring会先从一级缓存中去找到目标Bean,如果发现一级缓存中没有便会去二级缓存中去找
2> 如果一、二级缓存中都没有找到,意味着该目标Bean还没有实例化(早期Bean)。于是,Spring容器会实例化目标Bean,然后将目标Bean放入到二级缓存中,同时,加上标记是否存在循环依赖。如果不存在循环依赖便会将目标Bean存入到二级缓存
3> 否则,便会标记该Bean存在循环依赖,然后将等待下一次轮询赋值,也就是解析@Autowired注解。等@Autowird(成熟Bean),会将目标Bean存入到一级缓存
第三级缓存的作用是用来存储代理Bean的,当调用getBean()方法之后,发现目标Bean需要通过代理工程来创建,此时会将创建好的实例保存到三级缓存,最终也会赋值好的Bean同步到一级缓存中
早期Bean:刚初始化的Bean
成熟Bean:完成注入的Bean
在Spring三级缓存的设计下,我画了一张图来描述一下其工作原理:

Spring本身只能解决单实例存在的循环依赖问题,存在以下四种情况需要人为干预:
1> 多实例的Setter注入导致的循环依赖,需要把Bean改成单例
2> 构造器注入导致的循环依赖,可以通过@Lazy注解
3> DependsOn导致的循环依赖,找到注解循环依赖的地方,迫使它不循环依赖
4> 单例的代理对象Setter注入导致的循环依赖
① 可以使用Lazy注解
② 或者使用@DependsOn注解指定加载先后关系
在实际开发中,出现循环依赖的根本原因还是在代码设计的时候,因为模块的耦合度较高,依赖关系复杂导致的,我们应该尽可能地从系统设计角度去考虑模块之间的依赖关系,避免循环依赖地问题。
三级缓存的核心思想:就是把Bean的实例化和Bean里面的依赖注入进行分离
总结:
① 采用一级缓存存储成熟Bean实例,采用二级缓存来存储早期Bean实例
② 通过早期Bean实例作为突破口,解决循环依赖问题。
③ 至于第三级缓存,主要是解决代理对象的循环依赖问题。
详细解释一下Spring是如何解决循环依赖问题的的更多相关文章
- Spring是如何解决循环依赖的
前言 在面试的时候这两年有一个非常高频的关于spring的问题,那就是spring是如何解决循环依赖的.这个问题听着就是轻描淡写的一句话,其实考察的内容还是非常多的,主要还是考察的应聘者有没有研究过s ...
- spring: 我是如何解决循环依赖的?
1.由同事抛的一个问题开始 最近项目组的一个同事遇到了一个问题,问我的意见,一下子引起的我的兴趣,因为这个问题我也是第一次遇到.平时自认为对spring循环依赖问题还是比较了解的,直到遇到这个和后面的 ...
- Spring 是如何解决循环依赖的?
前言 相信很多小伙伴在工作中都会遇到循环依赖,不过大多数它是这样显示的: 还会提示这么一句: Requested bean is currently in creation: Is there an ...
- 听说你还不知道Spring是如何解决循环依赖问题的?
Spring如何解决的循环依赖,是近两年流行起来的一道Java面试题. 其实笔者本人对这类框架源码题还是持一定的怀疑态度的. 如果笔者作为面试官,可能会问一些诸如"如果注入的属性为null, ...
- Spring三级缓存解决循环依赖
前提知识 1.解决循环依赖的核心依据:实例化和初始化步骤是分开执行的 2.实现方式:三级缓存 3.lambda表达式的延迟执行特性 spring源码执行逻辑 核心方法refresh(), popula ...
- Spring 如何解决循环依赖问题?
在关于Spring的面试中,我们经常会被问到一个问题,就是Spring是如何解决循环依赖的问题的. 这个问题算是关于Spring的一个高频面试题,因为如果不刻意研读,相信即使读过源码,面试者也不一定能 ...
- Spring解决循环依赖,你真的懂了吗?
导读 前几天发表的文章SpringBoot多数据源动态切换和SpringBoot整合多数据源的巨坑中,提到了一个坑就是动态数据源添加@Primary接口就会造成循环依赖异常,如下图: 这个就是典型的构 ...
- Spring如何解决循环依赖,你真的懂了?
导读 前几天发表的文章SpringBoot多数据源动态切换和SpringBoot整合多数据源的巨坑中,提到了一个坑就是动态数据源添加@Primary接口就会造成循环依赖异常,如下图: 这个就是典型的构 ...
- 浅谈Spring解决循环依赖的三种方式
引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种: ...
- Spring ioc(4)---如何解决循环依赖
前面说到对象的创建,那么在创建的过程中Spring是怎么又是如何解决循环依赖的呢.前面提到有个三级缓存.就是利用这个来解决循环依赖.打个比方说实例化A的时候,先将A创建(早期对象)放入一个池子中.这个 ...
随机推荐
- 使用js闭包封装一个原生的模态框
现在都是用的是人家封装的框架什么的,但是对于底层的了解也是必须的,不然就无法提升,下面分享一个2 years ago 自己封装的一个提示框 样式很简单(适用于任何分辨率) 具体代码如下 /** * 该 ...
- 基于electron25+vite4创建多窗口|vue3+electron25新开模态窗体
在写这篇文章的时候,查看了下electron最新稳定版本由几天前24.4.0升级到了25了,不得不说electron团队迭代速度之快! 前几天有分享一篇electron24整合vite4全家桶技术构建 ...
- C# 版本特性一览
前言 使用 C# 作为开发语言已经 15 个年头了,受惠于 C# 的不断更新,伴随着大量的新特性与大量语法糖,让我更加容易写出简洁.高效的代码.日常中大量特性早已信手拈来,当然从未尝试过的特性更是难以 ...
- 【python基础】循环语句-break关键字
1.break关键字 break关键字,其作用是在循环中的代码块遇到此关键字,立刻跳出整个循环,执行循环外的下一条语句. 其在while和for循环中的作用示意图如下: 1.1break在while循 ...
- Pytorch-如何在模型中引入可学习参数
错误实例: def init(self): self.w1 = torch.nn.Parameter(torch.FloatTensor(1),requires_grad=True).cuda() s ...
- Linux多线程(8.3 线程同步与互斥)
3. 线程的同步与互斥 为什么需要同步与互斥 一个进程运行时,数据存储在内存中.如果一个数据要进行运算,必须先将数据拷贝到寄存器中.比如要对栈上的一个int i进行"++"操作 ...
- java调用WebService(未完成)记录篇
背景: 因工作需要和一个Sap相关系统以WebService的方式进行接口联调,之前仅听过这种技术,但并没有实操过,所以将本次开发相关的踩坑进行记录 通过一个实例来认识webservice 服务端 首 ...
- 【原创】xenomai内核解析-xenomai实时线程创建流程
版权声明:本文为本文为博主原创文章,未经同意,禁止转载.如有错误,欢迎指正,博客地址:https://www.cnblogs.com/wsg1100/ 目录 问题概述 1 libCobalt中调用非实 ...
- BUUCTF-MISC-九连环(steghide隐写+伪加密)
开局一张图 丢入winhex里,尾部有其他文件名 kali中binwalk -e x.jpg 得到的zip中 图片打不开 丢入winhex,发现jpg处是伪加密 修改之后,解压可打开图片,另一个压缩包 ...
- 【技术积累】Vue.js中的事件【一】
Vue中的事件是什么 在Vue.js中,事件是用于处理用户交互的重要机制.Vue.js提供了一系列的事件处理方法和指令,使开发者能够方便地处理用户的各种操作. 1. 事件绑定:Vue.js通过v-on ...