一文弄懂Spring的循环依赖是如何解决的

前言
循环依赖产生的条件
循环依赖的解决
总结


前言

    

    接着上篇Spring IOC 源码一,本篇接着讲springioc 中循环依赖是如何处理的。



1.循环依赖产生的条件


一文弄懂Spring的循环依赖是如何解决的


一文弄懂Spring的循环依赖是如何解决的


大家应该有看过《盗梦空间》吧,梦与梦之间相互关联,梦与现实相互交替让整个故事扑朔迷离。如果最后小李子不认为她的老婆是虚拟的,那么他就会永远走不出梦境。


Bean的创建主要过程:实例化,属性注入,初始化


  1. 先创建DreamOne,实例化DreamOne,此时DreamOne中的属性dreamTwo为空,填充属性dreamTwo;

  2. 从ioc容器中查找DreamTwo中,DreamTwo并未创建,开始创建DreamTwo;

  3. 实例化DreamTwo,此时DreamTwo中的属性dreamOne为空,填充dreamOne;

  4. 从ioc容器中查找DreamOne,未找到,接着创建DreamOne.

    这样就形成了闭环。

1.1 解决思路

仔细再看上面的流程,会发现DreamOne其实是存在的,只不过DreamOne还不是一个完整的对象,只是完成了实例化还未初始化。如果在程序调用过程中,拥有了 某个对象的引用,后期再给他完成赋值操作,相当于提前暴露了某个不完整对象的引用,这样就能够提前打破闭环。
    spring就是这样,提前暴露了对象的引用,将实例化和初始化分开操作。这样就解决了循环依赖。


2.循环依赖的解决


    在Spring IOC 源码一中有介绍,在实例化bean后,属性注入之前,将bean放入了三级缓存singletonFactories,此时添加的是一个函数式接口。目的是保证在整个容器运行的过程中同名的bean对象只有一个。

 

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

        // Instantiate the bean.
        // BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
        BeanWrapper instanceWrapper = null;
        // 单例模型,则从未完成的 FactoryBean 缓存中删除
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        // 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 包装的实例对象
        final Object bean = instanceWrapper.getWrappedInstance();
        // 包装的实例对象的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }


        // 如果有后置处理,则允许后置处理修改 BeanDefinition
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    // applyMergedBeanDefinitionPostProcessors
                    //调用属性合并后置处理器, 进行属性合并
                    //这里会进行 一些注解 的扫描
                    //CommonAnnotationBeanPostProcessor -> @PostConstruct @PreDestroy @Resource
                    //AutowiredAnnotationBeanPostProcessor -> @Autowired @Value
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                mbd.postProcessed = true;
            }
        }

        // 解决单例模式的循环依赖
        // 单例模式 & 运行循环依赖&当前单例 bean 是否正在被创建
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));

        if (earlySingletonExposure) {
            // 提前将创建的 bean 实例加入到三级缓存singletonFactories
            // 这里是为了后期避免循环依赖
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        Object exposedObject = bean;
        try {
            //对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性
            // 则会递归初始依赖 bean
            populateBean(beanName, mbd, instanceWrapper);
            //调用初始化方法
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        
        /**
         * 循环依赖处理
         * Spring 循环依赖的场景有两种:
         * 构造器的循环依赖
         * field 属性的循环依赖
         * 对于构造器的循环依赖,Spring 是无法解决的,只能抛出 BeanCurrentlyInCreationException 异常表示循环依赖
         */

        if (earlySingletonExposure) {
            // 获取 earlySingletonReference
            Object earlySingletonReference = getSingleton(beanName, false);
            // 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
            if (earlySingletonReference != null) {
                // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                // 处理依赖
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    
                }
            }
        }

        // Register bean as disposable.
        try {
            // 注册 bean
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        return exposedObject;
    }


2.1 三级缓存

为什么是函数式接口,而不是直接暴露实例化的bean?
在回答这个问题时,先问另外一个问题:如果一个对象需要被代理,或者说需要生成代理对象,那么要不要优先生成一个普通对象?


普通对象和代理对象是不能同时出现在容器中的,因此当一个对象需要被代理的时候,就要使用代理对象覆盖掉之前的普通对象。
     在实际的调用过程中,是没有办法确定什么时候对象被使用,所以就要求当某个对象被调用的时候,优先判断此对象是否需要被代理(一文弄懂AOP源码),类似于一种回调机制的实现,因此传入lambda表达式的时候,可以通过lambda表达式来执行对象的覆盖过程,getEarlyBeanReference()


因此,所有的bean对象在创建的时候都要优先放到三级缓存中在后续的使用过程中,如果需要被代理则返回代理对象,如果不需要被代理,则直接返回普通对象

2.2 属性注入    

        

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    
        /**
         * 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会
         */
        boolean continueWithPropertyPopulation = true;
    
        // 是否持有 InstantiationAwareBeanPostProcessor
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }
        // 如果后续处理器发出停止填充命令,则终止后续操作
        if (!continueWithPropertyPopulation) {
            return;
        }
        // bean 的属性值
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
            // 根据Bean配置的自动装配模式完成注入,默认是0,即不走以下逻辑
            // 如果设置了相关的依赖装配方式,会遍历Bean中的属性
            // 根据类型或名称来完成相应注入,无需额外配置
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            // 将 PropertyValues 封装成 MutablePropertyValues 对象
            // MutablePropertyValues 允许对属性进行简单的操作,
            // 并提供构造函数以支持Map的深度复制和构造。
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            // 根据名称自动注入
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            // 根据类型自动注入
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }
        // 是否已经注册了 InstantiationAwareBeanPostProcessors
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        // 是否需要进行依赖检查
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            // 从 bw 对象中提取 PropertyDescriptor 结果集
            // PropertyDescriptor:可以通过一对存取方法提取一个属性
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        // 对所有需要依赖检查的属性进行后处理
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        //调用AutowiredAnnotationBeanPostProcessor来完成属性的赋值
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                // 依赖检查,对应 depends-on 属性
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }

        if (pvs != null) {
            // 将属性应用到 bean 中
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }


❶处调用AutowiredAnnotationBeanPostProcessorpostProcessPropertyValues方法完成属性的赋值@Autowired原理

最终会调用


#DefaultListableBeanFactory.class
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    if (Optional.class == descriptor.getDependencyType()) {
        return createOptionalDependency(descriptor, requestingBeanName);
    }
    else if (ObjectFactory.class == descriptor.getDependencyType() ||
            ObjectProvider.class == descriptor.getDependencyType()) {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
    }
    else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
    }
    else {
        //判断注入的bean是否需要懒加载,
        //这里是spring解决构造函数循环依赖的处理逻辑
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                descriptor, requestingBeanName);

        // 如果没有标注@Lazy,则执行真正创建bean的过程
        if (result == null) {
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}


❶getLazyResolutionProxyIfNecessary

如果有标注@Lazy,则生成代理,详见@Autowired原理

这是spring解决构造函数循环依赖的方法。
❷doResolveDependency
如果没有懒加载,则进行真正创建Bean的过程。
再回到AbstractBeanFactory#doGetBean方法创建DreamTwo
后面创建DreamTwo和DreamOne类似,在实例化DreamTwo对象后,将函数式接口添加到三级缓存,再接着进入属性注入DreamOne.

一文弄懂Spring的循环依赖是如何解决的


接着又回到AbstractBeanFactory#doGetBean方法创建DreamOne,这个时候因为三级缓存中有了DreamOne的函数调用,所以和上面不同了。

2.3 循环依赖


    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        //
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        //
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {

            /**
             * containsBeanDefinition 中存在 beanName 相对应的 BeanDefinition
             */
            try {
                /**
                 * 合并父类相关属性
                 */
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                /**
                 * 获取依赖。
                 * 在初始化 bean 时解析 depends-on 标签时设置
                 */
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    // 迭代依赖
                    for (String dep : dependsOn) {
                        // 检验依赖的bean 是否已经注册给当前 bean
                        // 获取其他传递依赖bean
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //没有注册到依赖bean中
                        // 注册到依赖bean中
                        registerDependentBean(dep, beanName);
                        try {
                            // 调用 getBean 初始化依赖bean
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    //
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            /**
                             * beanName:bean 的名字
                             * mbd:已经合并了父类属性的(如果有的话)BeanDefinition
                             * args:用于构造函数或者工厂方法创建 bean 实例对象的参数
                             */
                             //
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

            
        }

        return (T) bean;
    }


直接看第二步getSingleton方法


#DefaultSingletonBeanRegistry.class
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //
        Object singletonObject = this.singletonObjects.get(beanName);
        // 缓存中的 bean 为空,且当前 bean 正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //加锁保证 二级缓存添加和三级缓存删除操作的原子性,同时二级缓存和三级缓存就没有必要用concurrentHashMap了
            synchronized (this.singletonObjects) {  
                // 从 earlySingletonObjects 获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // earlySingletonObjects 中没有,且允许提前创建
                if (singletonObject == null && allowEarlyReference) {
                    // 从 singletonFactories 中获取对应的 ObjectFactory
                    /**
                     * allowEarlyReference:从字面意思上面理解就是允许提前拿到引用。
                     * 其实真正的意思是是否允许从 singletonFactories 缓存中通过 getObject() 拿到对象,为什么会有这样一个字段呢?
                     * 原因就在于 singletonFactories 才是 Spring 解决 singleton bean 的诀窍所在
                     */
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    // ObjectFactory 不为空,则创建 bean
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();//类似回调覆盖 执行lambda 表达式   AOP
//
添加到二级缓存,同时从三级缓存中删除
                        this.earlySingletonObjects.put(beanName, singletonObject);//三级缓存升到二级缓存
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }



.首先从一级缓存singletonObjects中获取DreamOne,此时还是空,前面分析只有三级缓存中存在。只有在经历完整ioc创建成功后才能添加到一级缓存;
      .此时判断条件isSingletonCurrentlyInCreation


因为在创建Bean之前beforeSingletonCreation方法将bean添加到了singletonsCurrentlyInCreation集合中;Spring IOC 源码一(详见2.2)


.从二级缓存earlySingletonObjects 中获取,此时也为空;
.此时条件allowEarlyReference ,则从三级缓存  singletonFactories中获取。调用singletonFactory.getObject(),因为三级缓存添加的是函数式接口,所以会回调
getEarlyBeanReference方法。

一文弄懂Spring的循环依赖是如何解决的


这里会去获取实现了SmartInstantiationAwareBeanPostProcessor 的后置处理器,而aop的处理器AnnotationAwareAspectJAutoProxyCreator 正好实现了该方法。如果需要代理就会生成代理对象,否则就是原对象。一文弄懂AOP源码
我的例子里没有代理,所以这里返回原对象,即经过实例化后的DreamOne对象。

一文弄懂Spring的循环依赖是如何解决的


.添加到二级缓存earlySingletonObjects中,同时从三级缓存singletonFactories删除,保证容器中同名的对象只有一个。


    从三级缓存singletonFactories中获取到DreamOne后,DreamTwo可以顺利的继续执行属性注入过程了。紧接着开始实例化DreamTwo,该过程省略,详细过程请参考Spring IOC 源码一

       

 当DreamTwo完成实例化后,会再次调用 getSingleton(beanName, false)

    #AbstractAutowireCapableBeanFactory.class#doCreateBean
    if (earlySingletonExposure) {
        // 获取 earlySingletonReference
        Object earlySingletonReference = getSingleton(beanName, false);
        // 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
        if (earlySingletonReference != null) {
            // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            // 处理依赖
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                
            }
        }


  这次传入的allowEarlyReferencefalse,因为dreamTwo已经实例化完成,所以不需要提前暴露

#DefaultSingletonBeanRegistry.class
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //
        Object singletonObject = this.singletonObjects.get(beanName);
        // 缓存中的 bean 为空,且当前 bean 正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //加锁保证 二级缓存添加和三级缓存删除操作的原子性,同时二级缓存和三级缓存就没有必要用concurrentHashMap了
            synchronized (this.singletonObjects) {  
                // 从 earlySingletonObjects 获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // earlySingletonObjects 中没有,且允许提前创建
                if (singletonObject == null && allowEarlyReference) {
                    // 从 singletonFactories 中获取对应的 ObjectFactory
                    /**
                     * allowEarlyReference:从字面意思上面理解就是允许提前拿到引用。
                     * 其实真正的意思是是否允许从 singletonFactories 缓存中通过 getObject() 拿到对象,为什么会有这样一个字段呢?
                     * 原因就在于 singletonFactories 才是 Spring 解决 singleton bean 的诀窍所在
                     */
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    // ObjectFactory 不为空,则创建 bean
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();//类似回调覆盖 执行lambda 表达式   AOP
                        this.earlySingletonObjects.put(beanName, singletonObject);//三级缓存升到二级缓存
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }


此时,二级缓存earlySingletonObjects中有DreamOne对象,三级缓存singletonFactories中有DreamTwo对象。当从二级缓存中没有找到DreamTwo时,因为allowEarlyReference是false,所以不会再从三级缓存中获取DreamTwo。

最后创建出来的DreamTwo对象是

一文弄懂Spring的循环依赖是如何解决的


DreamTwo创建成功后,回到创建Bean时函数回调地方。


#DefaultSingletonBeanRegistry.class
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        //全局加锁
        synchronized (this.singletonObjects) {
            // 从缓存中检查一遍
            //因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
            Object singletonObject = this.singletonObjects.get(beanName);
            //  为空,开始加载过程
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
            
                //加载前置处理,将bean的状态修改为正在创建中
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 初始化 bean
                    // 这个过程其实是调用 createBean() 方法
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    //后置处理,将bean的状态从正在创建中移除
                    afterSingletonCreation(beanName);
                }
                // 加入缓存中
                if (newSingleton) {
                    /**
                     * 一级缓存添加
                     */
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }


❶afterSingletonCreation

protected void afterSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
}
从正在创建的单例bean集合singletonsCurrentlyInCreation中removed掉DreamTwo。(在第一次调用getSingleton从三级缓存singletonFactories中获取bean时,会做为判断条件)。


❷addSingleton

    将创建好的DreamTwo对象添加到一级缓存中。


#DefaultSingletonBeanRegistry.class
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);
    }
}


此时,二级缓存earlySingletonObjects中有DreamOne对象,三级缓存singletonFactories中有DreamTwo对象

 所以会将DreamTwo从三级缓存singletonFactories中删掉,将经过ioc完整的DreamTwo对象添加到一级缓存singletonObjects中。
         完成DreamTwo的创建后,再回到DreamOne的属性注入部分,设置DreamTwo的value值。后续步骤基本很类似,省略。

到这里spring的循环依赖就解决了。

     

3.总结


三级缓存是否都需要?


首先回顾一下三级缓存分别的创建销毁时间


三级缓存:createBeanInstance之后:addSingletonFactory

二级缓存:第一次从三级缓存确定对象是代理对象还是普通对象的时候,同时删除三级缓存getSingleton

一级缓存:生成完整对象之后放到一级缓存,删除二三级缓存:addSingleton


从上诉分析中可以分析出,spring解决循环依赖的关键是

实例化和初始化分开操作

        将bean的几种状态:完成实例化,但未完成初始化;是否需要代理;完整状态通过不同的HashMap存储。所以便有了三级缓存。

3.1 如果没有三级缓存

如果没有三级存储, Spring 选择二级缓存来解决循环依赖的话,那么就意味着所有Bean都需要在实例化完成之后就立马判断是否需要生成代理对象而Spring的设计原则是在Bean初始化完成之后才为其创建代理
因为aop的原理是实现了SmartInstantiationAwareBeanPostProcessor的后置处理方法postProcessAfterInitialization来创建代理对象。详见Spring IOC 源码一
    如果提前创建代理,则有违背spring的设计原则;因为循环依赖的出现,如果不创建代理,后面就没有机会再创建代理对象,注入的就是原始对象,也会产生错误。


    还有另外一个方面的角度解析,详见一文弄懂AOP源码,站在的立场不一样,基于代理的代码优化角度来看的,这是我个人的一种看法,欢迎指正。

3.2 springBoot高版本循环依赖报错问题


Springboot2.6之后的版本,默认把循环依赖给禁用了。如果项目中存在循环依赖,需要添加一行配置


spring.main.allow-circular-references=true

否则会启动报错,说明Spring是不太赞成我们用循环依赖的。当有循环依赖产生的时候,这时候我们需要检查一下我们设计可能出了问题。




一文弄懂Spring的循环依赖是如何解决的
关注我的你,是最香哒!














原文始发于微信公众号(小李的源码图):一文弄懂Spring的循环依赖是如何解决的

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/145405.html

(0)
青莲明月的头像青莲明月

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!