1、什么是Spring中的循环依赖

循环依赖就是循环引用,也就是两个或者两个以上的Bean相互持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。

2、Spring处理循环依赖的机制

无法解决的循环依赖问题:

  • 单例Bean构造函数的循环依赖
  • prototype原型的循环依赖 (对与原型Bean的初始化过程中不论是通过构造器参数循环依赖还是通过setXxx方法产生循环依赖,Spring都会直接报错处理BeanCurrentlyInCreationException)
  • 构造器的循环依赖问题⽆法解决,只能拋出 BeanCurrentlyInCreationException 异常

解决单例Bean的属性注入的循环依赖问题

1、原理

在解决属性循环依赖时,spring采⽤的是提前暴露对象的⽅法。Spring 的循环依赖的理论依据基于 Java 的引⽤传递,当获得对象的引⽤时,对象的属性是可以延后设置的,但是构造器必须是在获取引⽤之前。Spring通过setXxx或者@Autowired⽅法解决循环依赖其实是通过提前暴露⼀个ObjectFactory对象来完成的,简单来说ClassA在调⽤构造器完成对象初始化之后,在调⽤ClassA的setClassB⽅法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中。

  • Spring容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器。
  • ClassA调⽤setClassB⽅法,Spring⾸先尝试从容器中获取ClassB,此时ClassB不存在Spring
    容器中。
  • Spring容器初始化ClassB,同时也会将ClassB提前暴露到Spring容器中
  • ClassB调⽤setClassA⽅法,Spring从容器中获取ClassA ,因为第⼀步中已经提前暴露了
    ClassA,因此可以获取到ClassA实例
  1. ClassA通过spring容器获取到ClassB,完成了对象初始化操作。
  • 这样ClassA和ClassB都完成了对象初始化操作,解决了循环依赖问题。

原理图大概如下:

3、Spring源码分析循环依赖问题

准备:创建了两个Bean,#CircularReferenceBean和#ItBean,两个bean相互依赖,通过setXxx方法进行注入。

1、以new ClassPathXmlApplicationContext("classpath:applicationContext.xml")为入口进行源码跟踪。进入到AbstractBeanFactory#doGetBean方法,获取Bean。

先1 2 3 级缓存中拿bean,如果没有拿到,则创建。具体的逻辑如下

由于是第一次创建CircularReferenceBean,所以缓存中并没有,需要创建,走下面流程,解析bean标签里面的依赖信息,然后调用创建bean的方法。AbstractBeanFactory#doGetBean.getSingleton(),进入createBean方法,查看具体的创建逻辑。

进入之后,里面有doCreateBean方法,这是真正执行操作的方法,Spring中,真的的逻辑操作的方法都是doXxx为前缀的方法。下面代码为处理循环依赖的主要逻辑代码。

先判断是否需要先将bean放入到三级缓存中,如果是需要则将bean放入三级缓存,注意,此时的bean还没有初始化完成的。里面的属性信息都没有进行赋值。进入populateBean()方法对Bean进行属性的装配,这里面完成对bean中注入属性的分析和赋值。进入方法,主要关注这一段代码。

可以看到 CircularReferenceBean创建的时候需要注入一个id为ItBean的bean。进入applyPropertyValues方法,看看如何获取需要的属性的。AbstractAutowireCapableBeanFactory#applyPropertyValues方法中调用BeanDefinitionValueResolver#resolveValueIfNecessary方法

进入resolveReference方法,方法中最终通过getBean的方法获取所需要的ItBean。进入方法,可以看到创建ItBean和创建CircularReferenceBean的方法一样,都进入到了doCreateBean方法。创建ItBean的流程跟上面流程完全一致,创建的时候发现ItBean依赖CircularReferenceBean则跟上述流程一样getBean方法获取CircularReferenceBean,并进入到doCreateBean方法中,但是这个时候由于CircularReferenceBean是被放入到三级缓存中的,所以可以再三级缓存中直接获取到,并且将CircularReferenceBean放到2级缓存中。这样ItBean就创建成功了,CircularReferenceBean也可以正常依赖ItBean。

Spring中循环依赖问题相关推荐

  1. Spring中循环依赖的解决办法

    点击上方蓝色字体,选择"标星公众号" 优质文章,第一时间送达 1.什么是循环依赖? 循环依赖就是循环引用,就是两个或多个bean相互之间的持有对方. A类中有一个B类型的成员变量, ...

  2. Spring中循环依赖详解

    目录 一.循环依赖第一种情况 一.示例代码 二.源码分析: 三.debug调试截图 二.循环依赖第二种情况--构造函数 一.示例代码: 二.运行结果: 三.为什么构造函数的循环依赖不被允许? 四.报错 ...

  3. Spring IOC循环依赖问题

    Spring IOC循环依赖问题 什么是循环依赖 循环依赖其实就是循环引用, 也就是两个或者两个以上的Bean互相持有对方,形成闭环,例如:A依赖B,B依赖C,C又依赖于A. Spring中循环依赖的 ...

  4. Spring之循环依赖源码解析

    目录 1.什么是循环依赖? 2.为什么会出现循环依赖? 3.面对循环依赖问题,我们该如何思考解决? 4.Spring是怎么解决循环依赖的? 5.总结 1.什么是循环依赖? 有两个类Order.Cust ...

  5. 图解Spring解决循环依赖

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 来源:juejin.cn/post/684490412216 ...

  6. spring 循环依赖_简单说说 Spring 的循环依赖

    作者 | 田伟然 回首向来萧瑟处,归去,也无风雨也无晴. 杏仁工程师,关注编码和诗词. 前言 本文最耗时间的点就在于想一个好的标题, 既要灿烂夺目,又要光华内敛,事实证明这比砍需求还要难! 由于对象之 ...

  7. Spring当中循环依赖很少有人讲,今天让我们来看看吧

    网上关于Spring循环依赖的博客太多了,有很多都分析的很深入,写的很用心,甚至还画了时序图.流程图帮助读者理解,我看了后,感觉自己是懂了,但是闭上眼睛,总觉得还没有完全理解,总觉得还有一两个坎过不去 ...

  8. Spring当中循环依赖很少有人讲,今天一起来学习!

    网上关于Spring循环依赖的博客太多了,有很多都分析的很深入,写的很用心,甚至还画了时序图.流程图帮助读者理解,我看了后,感觉自己是懂了,但是闭上眼睛,总觉得还没有完全理解,总觉得还有一两个坎过不去 ...

  9. 被问麻了,Spring 如何处理循环依赖?

    点击关注公众号,利用碎片时间学习 前言 Spring如何处理循环依赖?这是最近较为频繁被问到的一个面试题,在前面Bean实例化流程中,对属性注入一文多多少少对循环依赖有过介绍,这篇文章详细讲一下Spr ...

最新文章

  1. 结对编程-马尔科夫链作业成绩
  2. SwiftSuspenders 1.6 浅出深入 深入 2
  3. build.xml编译报错Specified VM install not found: type Standard VM, name jdk1.7.0_45
  4. 奇怪吸引子---Aizawa
  5. 华为编程规范_华为 Java 编程规范出炉,究竟和官方文档有何不同?
  6. 高性能服务器架构思路【不仅是思路】
  7. 修改gitlab数据卷的位置
  8. 【算法】剑指 Offer 50. 第一个只出现一次的字符
  9. C | 扫雷游戏完整版
  10. php json对象转为字符串,JSON对象转化为字符串(附上代码详细解答)
  11. bo耳机h5使用说明_五分钟了解Bamp;O耳机音箱能不能买
  12. ideaIU-2021.3配置Git/SVN
  13. 抖音seo源码二次开发 抖音seo源码二次开发
  14. Day4 数据分析 Excel图表【零基础】
  15. linux 查看任务管理器,LINUX查看进程的4种方法(小结)
  16. 校园小说男主是计算机系,十大完本校园小说排行榜 经典好看的青春校园小说...
  17. 【Java 入门】(六)表设计
  18. background背景图片铺满背景并且不重复
  19. mahout探索之旅---频繁模式挖掘算法与理解
  20. 萧邦主的技术博客导航

热门文章

  1. mysql ansi nulls_sql server 的ANSI_NULLS设置
  2. 解析二维码的三种方式
  3. 蹭WiFi掉黑客陷进怎么破
  4. 黑苹果 MSI B360迫击炮 i5 8500 hdmi输出 bug处理
  5. Oracle入门笔记(二)——SQL Developer的基本使用
  6. python面向对象三大特性
  7. bios设置内存频率教程(图文教程)
  8. Zookeeper后端开发工具Curator的使用 | Curator对节点的增删改查 | ACL权限控制 | 分布式锁 | 分布式计数器 | 附带最新版本下载
  9. 抖音评论采集接口_抖音接口
  10. 智博 计算机试题库,智博教育计算机新大纲冲刺资料(一)-简答题.pdf