Spring源码分析之循环依赖及解决方案 (5)

没错!这个图就是这么简单,由于始终无法创建出一个对象,不管是早期对象或者完整对象,使得两个工厂对象反复的去获取对方,导致陷入了死循环。

那么,我们是否有办法解决这个问题呢?

我的答案是无法解决,如果有想法的小伙伴也可以自己想一想哦~

我们发现,在发生循环依赖时,只要循环链中的某一个点可以先创建出一个早期对象,那么在下一次循环时,就会使得我们能够获取到早期对象从而跳出循环!

而由于工厂对象与工厂对象间是无法创建出这个早期对象的,无法满足跳出循环的条件,导致变成了死循环。

那么此时Spring中会抛出一个什么样的异常呢?

当然是栈溢出异常啦!两个工厂对象一直相互调用,不断开辟栈帧,可不就是栈溢出有木有~

6. 工厂对象与代理对象

上面的情况是无法解决循环依赖的,那么这个情况可以解决吗?

答案是可以的!

我们分析了,一个循环链是否能够得到终止,关键在于是否能够在某个点创建出一个早期对象(临时对象),而代理对象在doCreateBean时,是会生成一个早期对象放入三级缓存的,于是该循环链得以终结。

具体过程我这里就不再细分析了,就交由小伙伴自己动手吧~

总结

以上我们一共举例了6种情况,通过分析,总结出这样一条定律:

在发生循环依赖时,判断一个循环链是否能够得到终止,关键在于是否能够在某个点创建出一个早期对象(临时对象),那么在下一次循环时,我们就能通过该早期对象进而跳出(打破)循环!

通过这样的定律,我们得出工厂Bean与工厂Bean之间是无法解决循环依赖的,那么还有其他情况无法解决循环依赖吗?

有的!以上的例子举的都是单例的对象,并且都是通过set方法形成的循环依赖。

假使我们是由于构造方法形成的循环依赖呢?是否有解决办法吗?

没有,因为这并不满足我们得出的定律

无法执行完毕构造方法,自然无法创建出一个早期对象。

假使我们的对象是多例的呢?

也不能,因为多例的对象在每次创建时都是创建新的对象,即使能够创建出早期对象,也不能为下一次循环所用!

好了,本文就到这里结束了,希望小伙伴们有所收获~

Spring IOC的核心部分到此篇就结束了,下一篇就让我们进行AOP之旅吧~

下文预告:Spring源码分析之AOP从解析到调用

Spring 源码系列

Spring源码分析之 IOC 容器预启动流程(已完结)

Spring源码分析之BeanFactory体系结构(已完结)

Spring源码分析之BeanFactoryPostProcessor调用过程(已完结)

Spring源码分析之Bean的创建过程(已完结)

Spring源码分析之什么是循环依赖及解决方案

Spring源码分析之AOP从解析到调用

Spring源码分析之事务管理(上),事物管理是spring作为容器的一个特点,总结一下他的基本实现与原理吧

Spring源码分析之事务管理(下) ,关于他的底层事物隔离与事物传播原理,重点分析一下

Spring Mvc 源码系列

SpringMvc体系结构

SpringMvc源码分析之Handler解析过程

SpringMvc源码分析之请求链过程

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgjfgf.html