什么是循环依赖?就是两个Bean相互引用,比如用@Autowire 相互注入。
 
那么Spring是如何解决这个问题的呢?在Bean还未完全实例化前(类只实例化了一部分),将bean提前暴露出来,可以被其他Bean引用。
 
源码解析:
 
问题1:什么情况下需要提前暴露?
 
Spring托管的bean是通过getBean()-->doCreateBean()创建的。
 
正常情况下,单例模式,第一次调用getBean单例初始化完成后,直接放入cache了,后面再次调用直接从cache拿,不用走doCreateBean 了。
 
0
 
 
当有循环依赖时候,第二次调用getBean代码earlySingletonExposure就会=true,那么
就会触发行提前暴露bean的逻辑。
 
关键代码:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 
AbstractAutowireCapableBeanFactory.doCreateBean();
 
0
 
 
 
问题2: 提前暴露出去的对象是指定类型的Bean的实例本身吗?
不是的,是一个ObjectFactory用于创建该Bean实例 。因为Spring AOP机制,bean在后续实例化过程中可能会被BeanPostProcess处理,生成一个Proxy对象。
 
问题3: 是怎么提前暴露出去的?
其实很简单,遍历所有的BeanPostProcessor ,看是不是SmartInstantiationAwareBeanPostProcessor 对象(该接口是Spring AOP的顶级接口),不是(不需要AOP)直接返回原始bean。SmartInstantiationAwareBeanPostProcessor 提供了一个后门getEarlyBeanReference,该方法提前先调用了proxy bean的生成方法 wrapIfNecessary(),也就是说,AOP提前切入了。
0
 
 
问题4: 提前暴露出去的bean和最终生成的bean是同一个吗?
SmartInstantiationAwareBeanPostProcessor 接口做了强制规定,要么是同一个proxy对象,要么直接放回原始bean(不需要AOP的类)。
0
 
下面用AbstractAutoProxyCreator这个具体实现类的代码作进一步说明。 方法postProcessAfterInitialization() 加了一个判断,如果之前调用了getEarlyBeanReference(),完成了AOP,这里就不重复调用wrapIfNecessary()了(只是从earlyProxyReferences 做了remove),从而保证是同一个proxy对象。
0
 
 
问题5:很多文档说的循环依赖是通过三级缓存解决的,这个说法是咋回事?
 
上面详细介绍了singletonFactories 怎么暴露出去的,三级缓存就是DefaultSingletonBeanRegistry类里面的三个map,缓存核心逻辑见下段代码,先找singletonObjects,找不到再从earlySingletonObjects找,还是没有直接用singletonFactories 工厂创建(里面对singletonObjects加了锁,防止并发错误)。
0
 
代码实践:
为了证明以上说法,我们简单写一点代码加以验证。
代码:https://gitee.com/zfj321/spring-sourcecode-study
然后在下面位置打一个断点,进行跟踪。
0
 
 
参考资料:
 
 
 
 

Spring循环依赖的问题的更多相关文章

  1. spring循环依赖问题分析

    新搞了一个单点登录的项目,用的cas,要把源码的cas-webapp改造成适合我们业务场景的项目,于是新加了一些spring的配置文件. 但是在项目启动时报错了,错误日志如下: 一月 , :: 下午 ...

  2. Spring 循环依赖

    循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...

  3. Springboot源码分析之Spring循环依赖揭秘

    摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...

  4. Spring 循环依赖的三种方式(三级缓存解决Set循环依赖问题)

    本篇文章解决以下问题: [1] . Spring循环依赖指的是什么? [2] . Spring能解决哪种情况的循环依赖?不能解决哪种情况? [3] . Spring能解决的循环依赖原理(三级缓存) 一 ...

  5. Spring循环依赖的解决

    ## Spring循环依赖的解决 ### 什么是循环依赖 循环依赖,是依赖关系形成了一个圆环.比如:A对象有一个属性B,那么这时候我们称之为A依赖B,如果这时候B对象里面有一个属性A.那么这时候A和B ...

  6. 这个 Spring 循环依赖的坑,90% 以上的人都不知道

    1. 前言 这两天工作遇到了一个挺有意思的Spring循环依赖的问题,但是这个和以往遇到的循环依赖问题都不太一样,隐藏的相当隐蔽,网络上也很少看到有其他人遇到类似的问题.这里权且称他非典型Spring ...

  7. Spring — 循环依赖

    读完这篇文章你将会收获到 Spring 循环依赖可以分为哪两种 Spring 如何解决 setter 循环依赖 Spring 为何是三级缓存 , 二级不行 ? Spring 为啥不能解决构造器循环依赖 ...

  8. 帮助你更好的理解Spring循环依赖

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

  9. spring 循环依赖的一次 理解

    前言: 在看spring 循环依赖的问题中,知道原理,网上一堆的资料有讲原理. 但今天在看代码过程中,又产生了疑问. 疑问点如下: // 疑问点: 先进行 dependon 判断String[] de ...

  10. 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

    本次博客的目标 1. 手写spring循环依赖的整个过程 2. spring怎么解决循环依赖 3. 为什么要二级缓存和三级缓存 4. spring有没有解决构造函数的循环依赖 5. spring有没有 ...

随机推荐

  1. mybatis批量添加数据的三种方式

    原文地址:https://www.cnblogs.com/gxyandwmm/p/9565002.html

  2. 焦大:seo思维光年(上)检索的价值观

    http://www.wocaoseo.com/thread-55-1-1.html 检索的价值观是什么?最近很多人咨询我这个问题,因为在百度上根本找不到相关的资料,其实这个东西也是我自己总结的,比如 ...

  3. SpringCloud Alibaba Nacos 服务注册

    业务服务接入Nacos服务治理中心 启动Nacos访问地址为:http://101.200.201.195:8848/nacos/ 创建bom工程用于管理依赖(下方附加源码地址) 准备工作完成后开始接 ...

  4. 【Android】Scrollview返回顶部,快速返回顶部的功能实现,详解代码。

    作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 首先给大家看一下我们今天这个最终实现 ...

  5. Selenium 如何复用浏览器【解决扫码登录等问题】

    Selenium中复用已经打开的浏览器进行自动化测试,可以辅助我们解决某些登录需要扫二维码之后,才能进行的操作 目前只支持谷歌Chrome浏览器,那需要做哪些准备操作呢?往下看 1.windows和M ...

  6. vue-element-admin改造接入后台,搭建有来商城youlai-mall后台前端管理平台

    一. 前言 本篇基于有来商城youlai-mall微服务项目,搭建后台前端管理平台,技术选型希望通过本篇文章你可以,技术解决方案选择了vue-element-admin.希望通过本篇文章你可以vue- ...

  7. 剑指 Offer 48. 最长不含重复字符的子字符串

    题目描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度. 示例1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 & ...

  8. 教你用OpenCV 和 Python给证件照换底色(蓝底 <->红底->白底)

    在我们的生活中常常要用到各种底色要求的证件电子照,红底.蓝底.或者白底,而假如你手上只有一种底色的证件照,你又不想再去拍又不会PS怎么办?今天教你们用OpenCV和Python给你的证件照换底色. P ...

  9. C#程序执行时设置刷新等待

    背景 C#在进行某些调用操作时需要隐藏背景,等待刷新. 步骤 1.前端设置 <!--Loading Mask Region--> <div> <div id=" ...

  10. Salesforce LWC学习(二十五) Jest Test

    本篇参看: https://trailhead.salesforce.com/content/learn/modules/test-lightning-web-components https://j ...