循环依赖
实例化Bean是一个非常复杂的过程,而其中最比较难以理解的就是对循环依赖的解决,不管之前读者有没有对循环依赖方面的研究,这里需要介绍一下:
什么是循环依赖
这个不多做介绍,但是循环依赖会带来内存溢出的错误。
Spring是如何解决循环依赖
Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?
在Spring中将循环依赖的处理分成了3种情况。
构造器循环依赖
表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。
Spring容器将每一个正在创建的bean标识符放在一个“当前创建bean池”中,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建bean过程中发现自己已经在"当前创建bean池"中时,将抛出BeanCurrentlyInCreationException异常标识循环依赖;而对于创建完毕的bean将从“当前创建Bean池”中清楚掉。
setter循环依赖
表示通过setter注入方法构成的循环依赖。对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(比如setter注入)的bean来完成的。而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使得其他bean能引用到该bean。
这个检测的过程和上面的做法相似,只不过是先将原先的bean创建好,再调用setter方法注入依赖!
prototype范围的依赖处理
对应prototype作用域bean,Spring容器无法完成依赖注入,因为Spring容器不进行缓存“prototype”作用域的bean,因此无法提前暴露一个创建中的bean。
对于“singleton”作用域,可以通过setAllowCircularReference(false);来禁用循环引用,对于“prototype”不做循环依赖的检查。
这里有一篇比较好的博文,https://www.iflym.com/index.php/code/201208280001.html ,他的其他文章也很精彩!