spring循环依赖有两种情况:
1.构造器循环依赖
构造器循环依赖是没办法姐解决的,只能抛出BeanCurrentlyCreationException.
因为spring在创建bean的时候,发现创建的bean依赖其他bean,这时候spring会将该bean放入一个缓冲池(正在创建的缓冲池),然后再去创建其依赖的bean(每次创建bean的时候都会去校验这个bean时是否在缓冲池中),直到最后一个依赖bean成功创建,没成功创建一个bean,就会从缓冲池中删除这个bean的状态
例如:
A 依赖 B,B依赖C ,C依赖A,那么在创建A的时候,发现A依赖B,那么spring会把A打上一个标记(正在创建)放进缓冲池,转而去创建B,发现B又依赖C,同样会把B打上一个标记,转而去创建C,在创建C的时候,发现C依赖A,则去创建A,这时候在创建A的时候发现A已经在缓冲池中了,表示这时候出现了循环依赖,就抛出异常
2.setter循环依赖
对于setter循环依赖,spring只能解决单例作用域bean的setter循环依赖,可以通过setAllowCircularReferences(false)来禁用循环引用。
例如 A setter依赖B ,B setter依赖C, Csetter依赖A
1.在构造A的时候,先使用A默认的构造器初始化A,并暴露一个关于A的ObjectFactory放到SinglonFactory的map中缓存起来,然后setter注入B,这时候发现B还没有初始化,会把A打上一个正在创建的标记,并缓存起来,转而去初始化B
2.初始化B的过程跟A一样,会暴露一个ObjectFactory到singLonFactory缓存起来,
3.接着初始化C,同样也会暴露一个ObjectFactory到singLonFactory缓存起来,这时候在setterA的时候,发现在singLonFactory中有关于A的ObjectFactory,那么就可以通过ObjectFactory提前暴露一个正在创建的A,这样就完成了C的注册,并删除正在创建缓存吃中C的状态
3.prototype作用域的bean无法完成依赖注入,因为spring在创建prototype作用域的bean的时候,是不会缓存其正在创建的状态,因此没办法提前暴露一个正在创建的bean
所以prototype作用域的bean出现循环依赖,则会抛BeanCurrentlyCreationException异常