为什么会出现循环依赖
其实这和Spring注入bean的流程相关的,bean的初始化是分为属性注入-》aware接口回调后再初始化的,所以这就导致如果两个类,比如A类和B类,A类中注入了B类,B类中又注入了A类的属性;
这个时候A这个Bean先被加载,属性注入的时候会去判断B是否被实例化,若是没有被实例化就要去实例化B,这时候的B是一个半成品的BeanDefinition;
然后接着B的属性注入,发现又依赖了A这个时候注入的是半成品的A;然后就完成了B的属性注入,接着实例化了B对象
紧接着再注入A中,A类再完成属性注入,实例化出A对象;其实Spring解决循环依赖,用了三级缓存;
- 一级缓存(singletonObjects)主要存放完成生命周期的Bean;
- 二级缓存(earlySingletonObjects)存放已经经过实例化或者经过aop的半成品的bean
- 三级缓存(singletonFactories)存放的是一个工厂,主要用于将Bean提前aop;
没有三级缓存可以解决循环依赖吗?
组合一:一级缓存 + 二级缓存
singletonObjects + earlySingletonObjects 理论可以解决依赖注入,也可以解决代理,但需要每次加入二级缓存都要是代理对象,如果没有代理就完全没有必要,同时也不符合 Spring 对 Bean 生命周期的定义。(对象都应该在创建之后再进行动态代理而不是单纯的实例化以后就急着进行代理,如果循环依赖就是没办法的事)
组合二:一级缓存 + 三级缓存
singletonObjects + singletonFactories 可以解决依赖注入的问题,但是没法解决代理的问题,若要进行代理从 ObjectFactory 中获取对象实例进行代理,但是这样每次获取对象都不是同一个
解决循环依赖的流程
创建A->实例化A