首页 > spring > spring 如何解决循环依赖问题的?

spring 如何解决循环依赖问题的?

作者:bin

spring使用了三级缓存去解决依赖问题的
我们在setter单例模式注入时,spring的bean加载过程是:
例如循环依赖关系:A->B->A

实现原理:

1.先加载A,依次判断(一级缓存)、(二级缓存)、(三级缓存)中是否有A,没有就将A加入(三级缓存)

2. A依赖B,先加载B
2.1 依次判断(一级缓存)、(二级缓存)、(三级缓存)中是否有B,没有就将B加入(三级缓存)
2.2 加载B的依赖,发现依赖A,依次从(一级缓存)、(二级缓存)、(三级缓存)中查找A,发现(三级缓存)有A,将A上升到(二级缓存)中
2.3 将A注入B的引用,完成B的加载,将B从(三级缓存)升级至(一级缓存)中

3.A依赖的B加载完了,继续加载A完成。将A从(二级缓存)上升到(一级缓存)。

关键源码:

AbstractAutowireCapableBeanFactorydo.CreateBean

中,就先将bean放入singletonFactories(三级缓存)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
	throws BeanCreationException {
.....

//提前缓存单例,以便即使在诸如BeanFactoryAware之类的生命周期接口触发时也能够解析循环引用。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
    if (logger.isTraceEnabled()) {
        logger.trace("Eagerly caching bean '" + beanName +
                "' to allow for resolving potential circular references");
    }
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}


核心判断代码

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

/**(一级缓存)已经完成加载的单例缓存. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/**(二级缓存)早期的单例对象缓存集合. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/**(三级缓存)单例的工厂Bean缓存集合. */ 
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
......

//以此从singletonObjects(一级缓存中)、earlySingletonObjects(二级缓存)、singletonFactories(三级缓存)中查找
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;
}

您必须 [ 登录 ] 才能发表留言!