一、循环依赖

循环引用,也可以叫做循环依赖,就是A类依赖了B类,B类又依赖C类,C类又依赖A类,循环引用的bean之间必然会构成一个环,如下图所示,A、B、C之间构成了一个环形。

spring.png

二、依赖注入

Spring中依赖注入的方式有两种,属性注入与构造器注入。

Spring中的bean根据作用域的不同,可以大体分为两类,singleton和prototype。singleton在一个容器中,只会有一个实例;而prototype在每次调用时,都会产生一个新的实例。

在Spring中,单例bean有延迟加载和立即加载两种加载方式,其中立即加载模式会在容器启动的时候就创建bean,而延迟加载会在容器启动后,使用到bean的时候再加载它。本文分析一律使用延迟加载,因为有时候单例bean的加载顺序,会影响到创建bean的成功或失败。

循环依赖的问题

当Spring容器在创建A时,会发现其引用了B,从而会先去创建B。同样的,创建B时,会先去创建C,而创建C时,又先去创建A。最后A、B、C之间互相等待,谁都没法创建成功。

循环依赖的解决方案

要想打破这个环,那么这个环中至少需要有一个bean可以在自身的依赖还没有得到满足前,就能够被创建出来(最起码要被实例化出来,可以先不注入其需要的依赖)。这种bean只能是通过属性注入依赖的类,因为它们可以先使用默认构造器创建出实例,然后再通过setter方法注入依赖。而通过构造器注入依赖的类,在它的依赖没有被满足前,无法被实例化。而且这个bean,还必须是singleton,不能是prototype。