Spring循环依赖问题
一、spring循环依赖
Spring解决循环依赖是有前置条件的
出现循环依赖的Bean必须要是单例
依赖注入的方式不能全是构造器注入的方式(很多博客上说,只能解决setter方法的循环依赖,这是错误的)
其中第一点应该很好理解,第二点:不能全是构造器注入是什么意思呢?我们还是用代码说话
@Component
public class A {
// @Autowired
// private B b;
public A(B b) {
}
}
@Component
public class B {
// @Autowired
// private A a;
public B(A a){
}
}
在上面的例子中,A中注入B的方式是通过构造器,B中注入A的方式也是通过构造器,这个时候循环依赖是无法被解决,如果你的项目中有两个这样相互依赖的Bean,在启动时就会报出以下错误:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?
为了测试循环依赖的解决情况跟注入方式的关系,我们做如下四种情况的测试
依赖情况 | 依赖注入方式 | 循环依赖是否被解决 |
---|---|---|
AB相互依赖(循环依赖) | 均采用setter方法注入 | 是 |
AB相互依赖(循环依赖) | 均采用构造器注入 | 否 |
AB相互依赖(循环依赖) | A中注入B的方式为setter方法,B中注入A的方式为构造器 | 是 |
AB相互依赖(循环依赖) | B中注入A的方式为setter方法,A中注入B的方式为构造器 | 否 |
从上面的测试结果我们可以看到,不是只有在setter方法注入的情况下循环依赖才能被解决,即使存在构造器注入的场景下,循环依赖依然被可以被正常处理掉。
二、spring解决循环依赖(三级缓存)
(1)、三级缓存定义
看源码的DefaultSingletonBeanRegistry中有三个 Map 对象
/** Cache of singleton objects: bean name to bean instance. */
/** 一级缓存,可以理解为单例池 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
/** 三级缓存,单例工厂缓存 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
/** 二级缓存,早期单例对象缓存 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
singletonObjects:存放初始化后的单例对象,也就是完成的 bean 对象
earlySingletonObjects:存放实例化,未完成初始化的单例对象(未完成属性注入的对象),也是用来解决性能问题
singletonFactories:存放 ObjectFactory 对象,存放的是工厂对象,也是用来解决 aop 的问题
(2)、核心方法refresh(刷新)
finishBeanFactoryInitialization方法
重点解析:解决循环依赖。
三级缓存可以解决循环依赖。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/90986.html