spring怎么解决循环依赖

spring怎么解决循环依赖?
首先会根据 beanName 从单例 bean 缓存中获取,如果不为空则直接返回

主要是从三个缓存中获取 (称他们为3级缓存),分别是:
singletonObjects (1 单例对象的cache)
earlySingletonObjects(2 提前暴光的单例对象的Cache )
singletonFactories (3 单例对象工厂的cache )
getSingleton() 整个过程如下:
首先从一级缓存 singletonObjects 获取,如果没有且当前指定的 beanName 正在创建,
就再从二级缓存中 earlySingletonObjects 获取,如果还是没有获取到且运行 singletonFactories 通过 getObject() 获取,
则从三级缓存 singletonFactories 获取,如果获取到则,通过其 getObject() 获取对象,
并将其加入到二级缓存 earlySingletonObjects 中 从三级缓存 singletonFactories 删除,这样就从三级缓存升级到二级缓存了

从缓存中获取,但是缓存中的数据从哪里添加进来的呢?
提前将创建好但还未进行属性赋值的的Bean放入缓存中
一个 bean 要具备如下条件才会添加至缓存中:
1、单例
2、运行提前暴露 bean
3、当前 bean 正在创建中
如果二级缓存(earlySingletonExposure)存在,singletonFactories 这个三级缓存才是解决 Spring Bean 循环依赖的诀窍所在。
同时这段代码发生在 createBeanInstance() 方法之后,也就是说这个 bean 其实已经被创建出来了,但是它还不是很完美(没有进行属性填充和初始化)
,但是对于其他依赖它的对象而言已经足够了(可以根据对象引用定位到堆中对象),能够被认出来了,
所以 Spring 在这个时候选择将该对象提前曝光出来让大家认识认识

所以我们基本上可以确定 Spring 解决循环依赖的方案了:Spring 在创建 bean 的时候并不是等它完全完成,
而是在创建过程中将创建中的 bean 的 ObjectFactory 提前曝光(即加入到 singletonFactories 缓存中),
这样一旦下一个 bean 创建的时候需要依赖 bean ,则直接使用 ObjectFactory 的 getObject() 获取了,也就是 getSingleton()中的代码片段了。

描述下就上面那个循环依赖 Spring 解决的过程:首先 A 完成初始化第一步并将自己提前曝光出来
(通过 ObjectFactory 将自己提前曝光),在初始化的时候,发现自己依赖对象 B,
此时就会去尝试 get(B),这个时候发现 B 还没有被创建出来,然后 B 就走创建流程,在 B 初始化的时候,同样发现自己依赖 C,C 也没有被创建出来,
这个时候 C 又开始初始化进程,但是在初始化的过程中发现自己依赖 A,于是尝试 get(A),这个时候由于 A 已经添加至缓存中(一般都是添加至三级缓存 singletonFactories )
,通过 ObjectFactory 提前曝光,所以可以通过 ObjectFactory.getObject() 拿到 A 对象,C 拿到 A 对象后顺利完成初始化,然后将自己添加到一级缓存中,
回到 B ,B 也可以拿到 C 对象,完成初始化,A 可以顺利拿到 B 完成初始化。到这里整个链路就已经完成了初始化过程了

总体就是 把循环的A初始化放到通过 ObjectFactory 放到 2级缓存 。。。 C尝试去缓存中 get A C拿到 A 对象后顺利完成初始化,然后将自己添加到一级缓存中,
回到 B ,B 也可以拿到 C 对象,完成初始化

Spring对单例的底层实现,到底是饿汉式单例还是懒汉式单例呢?
Spring框架对单例的支持是采用单例注册表的方式进行实现的

原文地址:https://www.cnblogs.com/webster1/p/12246160.html

时间: 2024-08-29 06:32:58

spring怎么解决循环依赖的相关文章

Spring 如何解决循环依赖的问题

Spring 如何解决循环依赖的问题 https://blog.csdn.net/qq_36381855/article/details/79752689 Spring IOC 容器源码分析 - 循环依赖的解决办法 https://www.imooc.com/article/34150 原文地址:https://www.cnblogs.com/tonggc1668/p/11751384.html

Spring源代码解析 ---- 循环依赖

一.循环引用: 1. 定义: 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比方CircularityA引用CircularityB,CircularityB引用CircularityC,CircularityC引用CircularityA.形成一个环状引用关系. 2. 代码演示样例: CircularityA public class CircularityA { private CircularityB circularityB; public CircularityA()

Spring 循环引用(三)AbstractFactoryBean 如何解决循环依赖

目录 Spring 循环引用(三)AbstractFactoryBean 如何解决循环依赖 1. 循环依赖问题 2. 准备实验 3. 原因分析 4. 解决方案 5. 还有什么问题 6. 总结 Spring 循环引用(三)AbstractFactoryBean 如何解决循环依赖 Spring 系列目录:https://www.cnblogs.com/binarylei/p/10198698.html 本章讨论的范围:AbstractFactoryBean 创建单例 Bean 过程中出现的循环依赖问

spring解决循环依赖

之前面试有被问到过,面试官很调皮,我擅长的点没有问,然后抽了一个点让我回答,这个点考察了源码的理解,当时只是大概记得是提前暴露,但是细节答得有些粗糙,特补充一下,,, protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == nul

Spring中的循环依赖

循环依赖 在使用Spring时,如果主要采用基于构造器的依赖注入方式,则可能会遇到循环依赖的情况,简而言之就是Bean A的构造器依赖于Bean B,Bean B的构造器又依赖于Bean A.在这种情况下Spring会在编译时抛出BeanCurrentlyInCreationException. Class A @Component public class ClassA { private ClassB classB; @Autowired public ClassA(ClassB class

Angular4---认证---使用HttpClient拦截器,解决循环依赖引用的问题

在angular4 项目中,每次请求服务端需要添加头部信息AccessToken作为认证的凭据.但如果在每次调用服务端就要写代码添加一个头部信息,会变得很麻烦.可以使用angular4的HttpClient来拦截每个请求,然后在头部添加上信息. 直接上代码实践 一.创建拦截器Service,实现HttpInterceptor的intercept方法 import { Injectable, Injector} from '@angular/core'; import {HttpEvent, Ht

spring循环依赖是怎么解决的?

回答:循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleA,则它们最终反映为一个环. Spring如何解决循环依赖? 假设场景如下,A->B->A 1.实例化A,并将未注入属性的A暴露出去,即提前曝光给容器Wrap2.开始为A注入属性,发现需要B,调用getBean(B)3.实例化B,并注入属性,发现需要A的时候,从单例缓存中查找,没找到时继而从Wrap中查找,从而完成属性的注入4.递归完毕之后回到A的实例化过程

Spring之循环依赖

转:http://my.oschina.net/tryUcatchUfinallyU/blog/287936 概述 如何检测循环依赖 循环依赖如何解决 Spring如何解决循环依赖 主要的几个缓存 主要步骤 Spring不能完全解决的循环依赖问题 面对Spring不能完全解决的现状,我们该如何处理 概述 入职的时候学习spring研究过循环依赖,现在再回顾下,发现啥都忘记了,还是得总结下来,故总结该文. 本文主要解决如下问题: 1.何为循环依赖 2.如何检测循环依赖 3.循环依赖可以如何解决 4

Spring循环依赖

Spring-bean的循环依赖以及解决方式 Spring里面Bean的生命周期和循环依赖问题 什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环.比如A依赖于B,B依赖于C,C又依赖于A.如下图: 注意,这里不是函数的循环调用,是对象的相互依赖关系.循环调用其实就是一个死循环,除非有终结条件. Spring中循环依赖场景有: (1)构造器的循环依赖 (2)field属性的循环依赖 其中,构造器的循环依赖问题无法解决,只能拋出BeanCurre