1.从哪知道spring能支持循环依赖
spring默认支持的,有个属性allowCircularReferences,并且提供api供我们修改,但是如果要生效需要在srping初始化之前就更改好。
例子
两个类 A B 循环依赖
2.循环依赖的过程
1.初始化扫描出来的类后,会调用getBean()方法去实例化扫描出来的类。之后调用doGetBean()
2.第一次调用getSingleton() 去一级缓存拿,拿不到
3.第二次调用getSingleton() 在set集合中记录A正在被创建,然后创建A后,如果支持循环依赖,那就放入二级缓存中。
4.当进行到属性填充的时候,A发现依赖了B。回去先从一级缓存中拿,如果没有就调用createBean创建B
5.B和A之前一样的流程
6.B第一次调用getSingleton() 为空,调用第二次getSingleton() ,同样会在set集合中记录自己正在被创建
7.B放入二级缓冲中,走到属性填充的时候,发现A正在被创建,
8.B先从一级缓存拿A,拿不到,从三级缓存拿,拿不到从二级缓冲拿,拿到了
9.把拿到的A放入三级缓存,移除二级缓冲的A
(这里为什么要放入三级缓存,其实是为了避免重复创建,因为二级缓存拿对象是执行一个工厂方法的,并不是直接拿对象,如果把工厂方法拿出的对象放进三级缓存中,那就可以避免再次执行工厂方法)
10.完成B,再接着完成A
为什么二级缓存是工厂对象,其实就是拿到对象之前能执行一些方法,比如完成AOP,我们知道一般的流程中,AOP是在注入属性之后完成的,那在循环引用当中,我们把AOP执行放到了工厂对象,提前完成AOP,如果不提前,B注入A的时候,A是没有AOP的