赣州新闻网

首页 / 科技

Spring循环依赖是什么?怎么解决

2020-04-13 · 赣州新闻网 · 科技

前言

Spring如何解决的循环依赖,是近两年流行起来的一道Java面试题。

其实笔者本人对这类框架源码题还是持一定的怀疑态度的。

如果笔者作为面试官,可能会问一些诸如“如果注入的属性为null,你会从哪几个方向去排T u d z s , Q查”这些场景题。

那么既然写S % 8了这篇文章,闲话少说,发车看看Spring是如何解决的循环依赖,以及带大家看清循环依赖的本质是什么。

正文

通常来说,如果问Spring内部如何解决循环依赖,一定是单默认的单例Bean中,属性互相引用的场景。

比如几个Beany ! Y ( M之间的互相引用:C Y I #

Spring循环依赖是什么?怎么解决

甚至自己“循环”依| H H U T _ p C B赖自己:

Spring循环依赖是什么?怎么解决

先说明前提:原型(Prototype)的场景是不支持循环依赖的,通常会走到AbstractBe* ) g ) = kanFactory类中下面的判断,抛出异常。


Spring循环依赖是什么?怎么解决


原因很好理解,创建新的A时,发现要注入原型字段B,又创建新的B发现要注入原型字段A...

这就套娃了, 你猜是先Stl / g fackOverflow还是OutOfMemory?

Spring怕你不好猜,就先抛出了BeanCurrentlyInCreationException

Spring循环依赖是什么?怎么解决

基于构造器g V q的m T m |循环依吧。

为什么成为后两个Map为垫脚石,假设最终放在singletonObjY g 8 ~ S T 2 Rects的Bean是你想要的一杯“凉白开”。

那么Spring准备了两个杯子,即singletonFactJ g G 0 c zories和earlySingletonObjects来回“倒腾”几番,把热水晾成“凉白开”放到singletonObjects中。

闲话不说,都浓缩在图里。

Spring循环依赖是什么?怎么解决

上面的是一张GID e U @ ~ + 8F,如果你没看到可能还没加载出来。三秒一帧,不是你电脑卡。

笔者画了17张图简化表述了Spring的主要步骤,GIFk y ? s @ 上方即是刚才提到的三级缓存,E f $ )下方展示/ _ n 3 , y V `是主要的几个方法。

当然了# I 6 ?,这个地步你肯定要结合Spring源码来看,要不肯定看不懂。

如果你只是想大概了解,或者面试,可以先记住笔者上文提到的“三级缓存”,以及下文即将要说的本质。

循环依赖的本m D q A p 0质

上文了S = t解完Spring如何处理循环依赖之后,让我们跳出“阅读源码”的思维,假设让你实现一个有以下特点的功能,你会怎么做?

  • 将指定的一些类实例为单例
  • 类中的字段O 6 8 2 1 &也都实例为单例
  • 支持循环* r ;依赖

举个例子,假设有类A:

public class A {
    private&` U C )nbsp;B b;
}

类B:

public&u X & ` + / ? z Tnbsp;class B {
   &nbsO [ 4 w x M tp;private A Q R H + K @ r `a;
}

说白了让你模仿Spring:假装A和B是被@Component修饰,并且类中的字段假装是@AutowI f +ired修饰的,处理完放到Map中。

其实非常简单,笔者写了一份粗糙的代码,可供参考:


Spring循环依赖是什么?怎么解决


这段代码的效果,其实就是处理了循环6 w ~依赖,并且处理完成后,cacheMap中放的就是完整的“Bean”了

Spring循环依赖是什么?怎么解决

这就是“循环依赖”的本质,而不是“Spring如何解决循环依赖”。

之所以要举这个例子,是发现一小部分盆友陷入了“阅读源码的泥潭”,而忘记了问题的本质。

为了看源码而看源码,结果一直看不B U . x j懂,却忘了本质是什么。

如果真看不懂,不如J : s K @ H ^先写出基础版本,逆推Spring为什么要这么实现,可能效果会更好。

whai L & u E qt?问! m 0 ! + Z x T题的本质居然是two sum!

看完笔者刚才的代码有没有似曾相识?没错,和twoO n [ ` / sum的解题是类似的。

不知道two sum是什么梗的,笔_ J w T U Y a t者和你介绍一下:

two sum是w ? + F O W刷题网站leetcode序号为1的题,也就是大多人的算法入门的M M K 4 /第一题。

常常被人调侃,有算法面的公司,被面试官钦定了,合的来。那就来一道two sum走走过场。

问题内容是:给定一个数组,给定一Y i g t 4 O个v 7 b f b @ $ }数字。返回数组中可以相加得到指定数字的两个索引。

比如:给定nuo ~ g H M { H w ims = , target = 9那么要返回 ,因为2 + 7 = 9

这道题的优解是,一次遍历+HashMap:


Spring循环依赖是什么?怎么解决


先去Map中找需要的数字,没有就将当前的数字保存在Map中,如果找到需要的数字,则一起返回。

和笔者上面的代码是不是一样?

先去缓存里找Bean,没有则实例化当前的Bean放到Map,如果有需要依赖当前Bean的,就能从Map取到。

结尾

如果你是上文笔者提到的A O 7 O @ +“陷入阅读源码的泥潭”的读者,上文应该可以帮助到你。

可能还有[ | b m盆友有疑问,为什么一道“two-sum”,Spring处理的如此复杂?这个想想Spring支持多少功能就知道了,各4 ? L O { y (种实例方式..各种注入方式..各种Bean的加载,校验..各种callback,aop处理等等u 4 C s Y W 3..

Spring可不$ e x 2 Q只有依赖注入,同样Java也不仅是Spring。如果我u b F a ! ! i们陷入了某个“牛角尖”,不妨跳出来看看,可能会更佳清晰哦。

设有工厂文章维护内容结尾上犹是什么循环