我们首说下,什么是“循环依赖”?
举个例子吧,对象张三依赖着对象李四,对象李四又依赖着对象张三,这就是循环依赖。两口子似的,彼此依赖,形影不离,缺一不可。
但是,如果真的程序中,出现了这种类似的情况,你会发现会无情地报错。
原因很好理解,我在创建张三的时候,发现需要李四,既然需要李四,那就再去创建李四,但是由于李四也依赖张三,所以又得先去创建张三,这不进去死胡同了吗?这么类似死锁了吗?那就对不起了兄弟,报错!
我们知道,spring很伟大,那么既然这么伟大,他老人家肯定有方式来解决这种情况,毕竟这种循环依赖的场景还是有的。
那么,就点题:spring是如何解决这种循环依赖而不报错的?
一句话:用到了大名鼎鼎的单例缓存池,准确地讲,是借助了三级缓存。
具体讲下呗?不要着急,听我慢慢道来。
要解释这个问题,就得考验下大家是否研究过源码了,是否对spring 创建Bean的过程是否了解了。我们还是以张三李四夫妻俩举例子。
假如对象张三需要依赖李四,并且是通过set属性的方式加入依赖。
从创建Bean的过程中我们看到,在创建张三时,是先从一个map中获取,既从singletonObjects获取,这个就是大名鼎鼎的单例缓存池。假如这里面没有,再去二级找,二级没有,再去三级找,毕竟是第一次创建,肯定都没有,那就去真的创建。当我把张三创建好了,但是还没给张三需要的属性赋值时,就把张三放入了三级缓存中。
注意,这个把张三放入三级缓存中这一步非常关键,非常关键,非常关键,非常关键,重要的事情说四遍。
接着发现他需要一个老婆,就是李四,也就是要为张三这个对象属性李四赋值,那么就去创建李四,在创建李四的时候,又发现需要张三,咦,这个时候,我们就发现不需要重新创建张三了,因为在刚才我们已经将创建好的张三放到缓存中了,取出来就可以了。
完美解决!合情合法的夫妻!
下面附上一个流程图,图文并茂嘛!
不知道大家有没有注意到,作者上面说的,“假如对象张三需要依赖李四,并且是通过set属性的方式加入依赖” 这句话,找找,上面肯定有这句话。
作者为什么要说这句话呢?
大家知道,创建依赖,是可以通过set属性的方式,构造器的方式,或者 @Bean的方式等等。我们上面说的就是set属性的方式,那么其它方式呢?构造器,或者 @Bean的方式能否通过这种缓存的方式解决循环依赖呢?另外,我们只是说单例的方式循环依赖,
如果是多实例的,能否解决循环依赖呢?
这也是面试常问,且能给面试官刮目相看的问题,您是否想知道呢?关注我,预知后事如何,且听下回分解吧。。。