iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >浅入浅出的讲解Spring循环依赖问题
  • 232
分享到

浅入浅出的讲解Spring循环依赖问题

2024-04-02 19:04:59 232人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录前言概念什么是循环依赖?报错信息通俗版理解两人对峙必须有一人妥协spring版理解实例化和初始化什么区别?三级缓存创建过程(简易版)创建过程(源码版)最后前言 最近有粉丝

前言

最近有粉丝问到了循环依赖问题,以后再有人问你,拿这篇“吊打”他。

概念

什么是循环依赖?

多个bean之间相互依赖,形成了一个闭环。比如:A依赖于B、B依赖于C、C依赖于A。

通常来说,如果问Spring容器内部如何解决循环依赖,一定是指默认的单例Bean中,基于set方法构造注入的属性互相引用的场景。

循环依赖的种类及能否解决如下:


名称 是否可解决循环依赖
构造器循环依赖
Setter循环依赖
Prototype作用域的循环依赖

报错信息

Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘myDao': Requested bean is currently in creation: Is there an unresolvable circular reference?

翻译一下

通过构造函数参数 0 表示的依赖关系未得到满足;嵌套的异常是 创建名称为'myDao'的bean时出错。请求的Bean目前正在创建中。是否存在一个无法解决的循环引用?

异常信息:bean当前创建异常org.springframework.beans.factory.BeanCurrentlyInCreationException。

通俗版理解

两人对峙

现在甲乙两个人,互相对峙,甲说乙先放,乙说甲先放。就是不开枪。

哎,就是玩!

相信这个场景大家在电视剧里都见过吧,最后一般是“反派死于话多”。

但是回到我们 spring里,我们是不希望有人死亡的,也就是必须两个bean都创建出来,怎么办?

必须有一人妥协

解决方案就是:必须有一个人先妥协。

甲说:我退一步,我先把弹夹卸了,你把枪放下。

乙一听就感动了,满含热泪的拿枪放下了。

甲一看乙没有打自己,也热泪盈眶,两人紧紧相拥。

从此过上了幸福美满的生活……

Spring版理解

回到我们spring里,先回顾一下bean的生命周期:

  • 实例化
  • 属性赋值
  • 初始化
  • 销毁

简单理解一下的上面的过程

实例化和初始化什么区别?

是不是只差了中间赋值的过程,那只实例化的bean可以使用吗?

当然不可以!

也就是说只实例化的bean是一个半成品,初始化之后才是成品,才可以使用。

现在A依赖B,B依赖A。

A对B说:我要完整的你

b也对a:我要完整的你

ok,两人打起来了,拿枪对峙。怎么解决?是不是得一个人妥协。

a说:算了吧,你给我个你的半成品,我将就一下。

b心里寻思,他用我的半成品创建一个完整的a,然后我就可以创建了。

心里这么想,嘴上就爽快答应着:行,没问题。

如此,a创建了完整的自己,b拿着a也完成了创建。

问题解决。

真的解决了吗?成品和半成品都存在哪里呢?

这就不得不提到大名鼎鼎的三级缓存。

三级缓存

spring提供了三级缓存来存放成品和半成品及工厂。位于DefaultSingletonBeanReGIStry类中。


public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {   
	
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
    
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
    
    private final Map<String, Object> earlySingletonObjects = new HashMap(16);
}

创建过程(简易版)

如果你是面试突击,建议把简易版被下来就可以应付面试了
等有时间再看源码版

假如A依赖B,B依赖A,那么这两个类之间形成了一个循环依赖

  • A先开始创建,通过其无参构造方法创建bean的实例,并将其实例放入到「二级缓存」提前暴露出来。A停止。
  • B开始创建,先去「一级缓存」找A的成品,找不到,再去「二级缓存」里找,还找不到,再去「三级缓存」里找,找到了A的创建工厂,通过工厂,拿到A的半成品,并将A放到「二级缓存」。
  • 拿到A后,B完成创建,将自己放入「一级缓存」。
  • 此时A继续创建,同样从「一级缓存」开始找,拿到B后完成创建,将自己放入「一级缓存」。

创建过程(源码版)

源码版建议配合Spring源码边debug边食用。

1、当我们在调用getBean()获取bean时,实际调用的是doGetBean() 方法。doGetBean() 想要获取 beanA ,于是调用 getSingleton() 方法从缓存中查找 beanA

2、在 getSingleton() 方法中,从「一级缓存」中查找,没有,返回 null

3、doGetBean() 方法中获取到 beanA 为 null ,于是走对应的处理逻辑,调用 getSingleton() 的重载方法(参数为 ObjectFactory 的)

4、在 getSingleton()方法中,先将 beanA_name 添加到一个集合中,用于标记该 bean 正在创建中,然后回调匿名内部类的 createBean 方法

5、进入 AbstractAutowireCapableBeanFactory#doCreateBean,先反射调用构造器创建出 beanA 的实例,然后判断,是否为单例,是否允许提前暴露引用(对于单例一般为true)、是否正在创建中(即是否是在第四步的集合中)判断为 true 则将 beanA 添加到「三级缓存」中

6、对 beanA 进行属性填充,此时检测到 beanA 依赖于 beanB ,于是查找 beanB

7、调用 doGetBean() 方法,和上面 beanA 的过程一样,到缓存中查询 beanB ,没有则创建,然后给 beanB 填充属性

8、此时 beanB 依赖于 beanA ,调用 getSingleton() 获取 beanA ,依次从一级、二级、三级缓存中找、此时从「三级缓存」中获取到 beanA 的创建工厂,通过创建工厂获取到 singletonObject ,此时这个 singletonObject 指向的就是上面在 doCreateBean() 方法中实例化的 beanA

9、这样 beanB 就获取到了 beanA 的依赖,于是 beanB 顺利完成初始化,并将 beanA 从「三级缓存」移动到「二级缓存」中

10、随后 beanA 继续他的属性填充工作,此时也获取到了 beanB ,beanA 也随之完成了创建,回到 getSingleton() 方法中继续向下执行,将 beanA 从「二级缓存」移动到「一级缓存」中

最后

到此这篇关于Spring循环依赖问题的文章就介绍到这了,更多相关Spring循环依赖内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 浅入浅出的讲解Spring循环依赖问题

本文链接: https://www.lsjlt.com/news/137901.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 浅入浅出的讲解Spring循环依赖问题
    目录前言概念什么是循环依赖?报错信息通俗版理解两人对峙必须有一人妥协Spring版理解实例化和初始化什么区别?三级缓存创建过程(简易版)创建过程(源码版)最后前言 最近有粉丝...
    99+
    2024-04-02
  • 浅谈Spring解决循环依赖的三种方式
    引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错。下面说一下Spring是如果解决循环依赖的。第一种:构造器参数循环依赖表示通过构造器注入构成的...
    99+
    2023-05-30
    spring 循环 依赖
  • spring循环依赖问题如何解决
    本篇内容介绍了“spring循环依赖问题如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、三种循环依赖的情况①构造器的循环依赖:这种...
    99+
    2023-07-02
  • 怎么解决Spring循环依赖问题
    本篇内容介绍了“怎么解决Spring循环依赖问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言循环依赖...
    99+
    2024-04-02
  • 如何解决Spring循环依赖问题
    本文小编为大家详细介绍“如何解决Spring循环依赖问题”,内容详细,步骤清晰,细节处理妥当,希望这篇“如何解决Spring循环依赖问题”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。公共代码package&nbs...
    99+
    2023-07-02
  • Spring循环依赖问题怎么解决
    在Spring中,循环依赖问题是指两个或多个bean之间出现相互依赖的情况。由于Spring容器默认使用单例模式管理bean,因此循...
    99+
    2023-08-31
    Spring
  • Spring循环依赖之问题复现详解
    目录简介问题复现1.构造器注入2.Feild注入多例(@AutoWired) 3.Setter注入多例(@AutoWired) 解决方案简介 说明 本文介绍Spr...
    99+
    2024-04-02
  • 怎么在spring中解决循环依赖问题
    怎么在spring中解决循环依赖问题?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。setter singleton循环依赖使用SingleSetterBeanA依赖Sing...
    99+
    2023-06-08
  • Spring中怎么处理循环依赖问题
    Spring中怎么处理循环依赖问题,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是循环依赖依赖指的是Bean与Bean之间的依赖关系,循环依赖指的是两个或者...
    99+
    2023-06-20
  • 深入浅出讲解Spring框架中依赖注入与控制反转及应用
    目录概念:使用对比1. 使用前:2. 使用后:理解控制反转(Ioc):IoC的应用方法 概念:      依赖注入(Dependency In...
    99+
    2024-04-02
  • spring bean的自动注入及循环依赖问题怎么解决
    这篇文章主要介绍了spring bean的自动注入及循环依赖问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇spring bean的自动注入及循环依赖问题怎么解决文章都会有所收获,下面我们一起来看看吧...
    99+
    2023-07-05
  • 关于spring循环依赖问题及解决方案
    目录一、三种循环依赖的情况比如几个Bean之间的互相引用 甚至自己“循环”依赖自己二、解决方案如何获取依赖三、解决循环依赖必须要三级缓存吗结论四、无...
    99+
    2024-04-02
  • Spring源码剖析之Spring处理循环依赖的问题
    前言 你是不是被这个骚气的标题吸引进来的,_ 喜欢我的文章的话就给个好评吧,你的肯定是我坚持写作最大的动力,来吧兄弟们,给我一点动力 Spring如何处理循环依赖?这是最近较为频繁被...
    99+
    2024-04-02
  • Bean的自动注入及循环依赖问题
    目录一、spring中的各种注入方式一、spring中的各种注入方式 对于是spring的注入前置知识、@Autowired、@Resource等的知识可以看其他文章,这里就不多说了...
    99+
    2023-03-23
    springbean的自动注入方式 循环依赖问题的解决
  • springbean循环依赖问题如何解决
    Spring框架可以通过使用构造函数注入和setter方法注入两种方式来解决循环依赖问题。1. 构造函数注入:在循环依赖的类中,通过...
    99+
    2023-09-29
    springbean
  • maven循环依赖问题如何解决
    Maven循环依赖问题可以通过以下几种方式解决:1. 重新设计项目结构:循环依赖通常是由于项目结构设计不合理引起的。可以重新考虑项目...
    99+
    2023-09-17
    maven
  • Spring使用三级缓存解决循环依赖的问题
    Spring如何使用三级缓存解决循环依赖在没开始文章之前首先来了解一下什么是循环依赖 @Component public class A { @Autowired ...
    99+
    2024-04-02
  • springboot怎么解决循环依赖问题
    在Spring Boot中解决循环依赖问题,可以尝试以下几种方法:1. 使用构造器注入:将循环依赖的对象注入到构造器中,并且使用`@...
    99+
    2023-09-27
    springboot
  • 如何解决Java循环依赖的问题
    今天就跟大家聊聊有关如何解决Java循环依赖的问题,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。最近看到一个问题:如果有两个类A和B,A类中有一个B的对象b,B类中有一个A的对象a,...
    99+
    2023-06-02
  • Spring循环依赖的解决方法
    这篇文章主要介绍Spring循环依赖的解决方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!循环依赖其实就是循环引用,很多地方都说需要两个或则两个以上的bean互相持有对方最终形成闭环才是循环依赖,比如A依赖于B,B...
    99+
    2023-06-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作