美文网首页
如何解决Spring循环依赖问题

如何解决Spring循环依赖问题

作者: 晏子小七 | 来源:发表于2021-03-09 18:06 被阅读0次

何为循环依赖?

循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如图:

循环依赖

如何解决?

① 主bean通过属性或者setter方法注入所依赖的bean,不是通过构造函数注入

② 通过三级缓存实现:singletonObjects,earlySingletonObjects和singletonFactories;

通过spring-beans包下的DefaultSingletonBeanRegistry类完成

//一级缓存singletonObject,一级缓存需要用JUC
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
//三级缓存singletonFactory,在synchronized中执行无需考虑线程安全
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
//二级缓存earlySingletonObjects,在synchronized中执行无需考虑线程安全
private final Map<String, Object> earlySingletonObjects = new HashMap(16);

主要是类中的getSingleton方法完成,我们看下getSingleton方法源码实现:

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //通过beanName获取一级缓存对象
    Object singletonObject = this.singletonObjects.get(beanName);
    //当前对象不在这个单例中 && bean正在创建中
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        synchronized(this.singletonObjects) {
            //获取二级缓存对象earlySingletonObjects
            singletonObject = this.earlySingletonObjects.get(beanName);
            //二级缓存对象不在此单例中而且允许创建
            if (singletonObject == null && allowEarlyReference) {
                //三级缓存对象创建
                ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //三级缓存对象创建成功并放入二级缓存中
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    //移除一级缓存
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }

    return singletonObject;
}

实现过程是这样的,创建主bean时通过getSingleton将主bean放入上述的isSingletonCurrentlyInCreation列表中,从而使上面的方法实现二三级缓存。

DefaultSingletonBeanRegistry类中还有一个public的getSingleton方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory){

    synchronized(this.singletonObjects) {
        //获取一级缓存
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            //...部分判断省略
            //将当前beanName放入singletonsCurrentlyInCreation中,以便解决循环依赖问题
            this.beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = this.suppressedExceptions == null;
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet();
            }

            try {
                //直接获取三级缓存中的对象
                //getObject方法会调用AbstractAutowireCapableBeanFactory的createBean方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            } catch ...省略部分代码
        }

        return singletonObject;
    }
}

看下createBean方法,本质是调用AbstractAutowireCapableBeanFactory的doCreateBean方法:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // 省略其他代码

    // 1\. 调用构造函数创建该bean对象,若不存在构造函数注入,顺利通过
    instanceWrapper = createBeanInstance(beanName, mbd, args);

    // 2\. 在singletonFactories缓存中,放入该bean对象,以便解决循环依赖问题
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

    // 3\. populateBean方法:bean对象的属性赋值
    populateBean(beanName, mbd, instanceWrapper);

    // 省略其他代码
}

注意<u style="box-sizing: border-box;">addSingleton</u>方法,最后,都会将单例bean对象放入一级缓存singletonObjects中,并移除存放提前曝光对象的二级缓存earlySingletonObjects和该bean对象的创建工厂缓存earlySingletonObjects,解决循坏依赖的问题

相关文章

网友评论

      本文标题:如何解决Spring循环依赖问题

      本文链接:https://www.haomeiwen.com/subject/srybqltx.html