没错!这个图就是这么简单,由于始终无法创建出一个对象,不管是早期对象或者完整对象,使得两个工厂对象反复的去获取对方,导致陷入了死循环。
那么,我们是否有办法解决这个问题呢?
我的答案是无法解决,如果有想法的小伙伴也可以自己想一想哦~
我们发现,在发生循环依赖时,只要循环链中的某一个点可以先创建出一个早期对象,那么在下一次循环时,就会使得我们能够获取到早期对象从而跳出循环!
而由于工厂对象与工厂对象间是无法创建出这个早期对象的,无法满足跳出循环的条件,导致变成了死循环。
那么此时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源码分析之请求链过程