探讨此问题之前,需要了解spring的ioc底层原理。
什么是循环依赖
代码中,两个或多个bean持有对方的引用,就会发生循环依赖,循环依赖会导致注入出现死循环,这是spring发生循环依赖的一个原因,循环依赖有三种形态:
a. 互相依赖:A依赖B,B依赖A
b. 三者依赖:A依赖B,B依赖C,C依赖A
c. 自我依赖:A依赖A
三级缓存设计
spring设计了三级缓存去解决循环依赖问题。创建当前实例时,会先在三级缓存里存入代理bean,当通过getBean获取一个对象实例的时候,spring会先从一级缓存去找,如果一级缓存没有找到,就去二级缓存去找,如果二级缓存没有,则去三级缓存去找,如果三级缓存没有,则表示该对象还没实例化,于是创建该实例,循环上述创建流程;如果没理解可以看下图示例
一级缓存存放完整的bean;
二级缓存存放早期的bean;
三级缓存存放生成对象的lambda表达式,及代理bean;
案例
场景:Aservice依赖Bservice,Bservice依赖Aservice。
流程:创建Aservice时,将生成A的lambda放入三级缓存,填充属性Bservice,一二三级缓存中都没,去创建Bservice,将生成B的lambda放入三级缓存,填充Aservice属性,发下三级缓存中有A,执行A的lambda生成Aservice对象,放入二级缓存,并删除A的三级缓存,执行B的lambda生成Bservice对象,放入一级缓存,并删除B的三级缓存;创建Aservice的流程中获取到Bservice对象之后,把二级缓存的Aservice对象删除,并放入一级缓存。