Spring循环依赖
Posted 起风了1412
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring循环依赖相关的知识,希望对你有一定的参考价值。
Spring是如何解决循环依赖的?
- 三级缓存
//一级缓存,用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二级缓存 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//三级缓存 存放 bean 工厂对象,用于解决循环依赖
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
- bean的创建会调用doCreateBean方法
- 先调用addSingletonFactory方法
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
- 再调用getSingleton方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
- 最后调用addSingleton方法
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
总结
- A先实例化(存入三级缓存),A初始化是发现依赖了B
- B实例化(存入三级缓存),B初始化发现依赖了A,缓存中取得了A后删除三级缓存中的A并存入二级缓存,B初始化完成,B存入一级缓存.
- 继续初始化A,由于B已经初始化完成,A也初始化完成,删除二级三级缓存.
以上是关于Spring循环依赖的主要内容,如果未能解决你的问题,请参考以下文章