天天看點

Spring源碼分析-循環依賴(Spring Framework 5.3.7-SNAPSHOT)

循環依賴的分類
  1. 主要分為屬性注入的循環依賴和構造器注入的循環依賴,先來看屬性注入的循環依賴,解決的核心在于singletonFactories這個緩存
    • 總的邏輯是:首先從Spring容器中擷取A的Bean時,調用createBeanInstance執行個體化構造函數之後,把A對應的執行個體化對象存入singletonFactories,接着在屬性指派populateBean這一步,會解析A的依賴屬性b,通過DefaultListableBeanFactory的doResolveDependency,從容器中又去擷取B對應的Bean
    • 同樣B執行個體化的過程與A一樣(至此A隻完成了執行個體化,沒有開始初始化),B完成執行個體化之後,把B對應的執行個體化對象存入singletonFactories,開始populateBean解析依賴的屬性a,同樣在DefaultListableBeanFactory的doResolveDependency,從容器中又去擷取A對應的Bean,由于第一步A存在于第三級緩存singletonFactories中,可以通過調用ObjectFactory的getObject方法(實質是調用lambda中,SmartInstantiationAwareBeanPostProcessor類型的後置處理器的getEarlyBeanReference方法)傳回單例對象,同時放入二級緩存earlySingletonObjects,并且移除三級緩存
    • B的屬性指派就完成,接着完成B剩下的初始化過程,最後程式的棧幀回退到第一步中A的populateBean方法,由于B依賴的a已完成指派,A依賴的b就也完成指派,至此互相引用的對象都有完整的值,解析完成。
  • 源碼分析如下:
/*--------------------------- 示例代碼 ------------------------*/
@Component
public class A {
    @Autowired
    private B b;
    
    public void handleA() {
        System.out.println("調用A的handleA方法");
    }
}

@Component
public class B {
    @Autowired
    private A a;
}
           
  • 在從Spring Ioc容器中擷取A對應的Bean時,首先調用AbstractBeanFactory的getBean,在doGetBean中,第一次調用getSingleton(beanName),從singletonObjects中取,當然擷取不到,傳回null,進行接下來的流程
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
    if (logger.isTraceEnabled()) {
        if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                    "' that is not fully initialized yet - a consequence of a circular reference");
        }
        else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
        }
    }
    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 對于單例,會運作下面的邏輯
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
    try {
        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;
    }
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}           
  • 對于單例,調用getSingleton(String beanName, ObjectFactory<?> singletonFactory)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        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!)");
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }
            // 将beanName放入singletonsCurrentlyInCreation
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                // 調用AbstractBeanFactory的lambda表達式,即:AbstractAutowireCapableBeanFactory的createBean方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                // // 将beanName從singletonsCurrentlyInCreation中移除
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                // 把建立好的單例對象singletonObject放入一級緩存,即:單例緩存池中
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}           
  • 首先嘗試從singletonObjects中擷取,如果擷取不到,把目前bean标記為正在建立
  • singletonFactory.getObject()調用createBean,再繼續調用doCreateBean,分為三步:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // factoryBeanInstanceCache存儲的是:beanName對應的FactoryBean執行個體對象
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 根據構造函數執行個體化,建立Bean執行個體
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 傳回的是原始對象,建立的Bean中屬性值為null
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                // 擴充點 TODO
                // 此步驟功能點包括:AutowiredAnnotationBeanPostProcessor對@Autowired預解析
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            } catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like 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");
        }
        // 此時bean沒有完成屬性注入,構造一個ObjectFactory放入第三級緩存singletonFactories中,
        // 便于下面的getSingleton方法,從singletonFactories中取出并執行lambda表達式
        // 第三級緩存,為了應對目前Bean在後面出現循環依賴的情況,就可以通過lambda表達式進行AOP的邏輯
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    // 對象已經暴露出去
    Object exposedObject = bean;
    try {
        // 填充屬性@Autowired
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化Bean、應用BeanPostProcessor
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        } else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            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);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}           
  • 通過反射,根據構造函數執行個體化createBeanInstance(此時A依賴的屬性b,為null)
  • 接下來判斷,如果滿足條件:單例 && 允許循環依賴 && 正在建立中,把目前beanName放入第三級緩存singletonFactories中
  • 調用populateBean開始屬性填充
  • 此時A依賴的屬性b,b被@Autowired标注,在doResolveDependency中,判斷出B的類型是Class,然後執行b的Bean的擷取邏輯,即:getBean("b")
  • 執行流程與建立a對應的Bean的邏輯相同,當執行到populateBean時,判斷出a的類型是Class,然後執行a的Bean的擷取邏輯,即:getBean("a"),重點關注populateBean方法中,AutowiredAnnotationBeanPostProcessor後置處理器的處理過程
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        } else {
            // Skip property population phase for null instance.
            return;
        }
    }

    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }

    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }

    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // 構造函數注入,set方法注入,@Value注入的邏輯在此處完成
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}           
  • AutowiredAnnotationBeanPostProcessor的屬性指派邏輯
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // @Autowired的預解析在populateBean這一步之前,applyMergedBeanDefinitionPostProcessors中進行的,解析結果會存入緩存,這裡直接從緩存中取
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 開始屬性的注入邏輯
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}           
  • InjectionMetadata的inject函數
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectedElement> elementsToIterate =
            (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        for (InjectedElement element : elementsToIterate) {
            // 對每個@Autowired辨別的屬性進行注入,根據element的類型不同(解析字段或者解析函數),執行不同的邏輯,這裡選擇字段解析
            element.inject(target, beanName, pvs);
        }
    }
}           
  • AutowiredFieldElement(AutowiredAnnotationBeanPostProcessor的内部類)的inject邏輯
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    if (this.cached) {
        try {
            value = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Unexpected removal of target bean for cached argument -> re-resolve
            value = resolveFieldValue(field, bean, beanName);
        }
    }
    else {
        // 解析字段的值
        value = resolveFieldValue(field, bean, beanName);
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        // 給目前對象的屬性逐一指派
        field.set(bean, value);
    }
}           
  • 解析字段的值
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    desc.setContainingClass(bean.getClass());
    Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
    Assert.state(beanFactory != null, "No BeanFactory available");
    TypeConverter typeConverter = beanFactory.getTypeConverter();
    Object value;
    try {
        // 解析依賴的屬性值,如果是對象,會重新調用getBean的邏輯,代碼需要一步步的跟
        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    }
    catch (BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    }
    synchronized (this) {
        if (!this.cached) {
            Object cachedFieldValue = null;
            if (value != null || this.required) {
                cachedFieldValue = desc;
                registerDependentBeans(beanName, autowiredBeanNames);
                if (autowiredBeanNames.size() == 1) {
                    String autowiredBeanName = autowiredBeanNames.iterator().next();
                    if (beanFactory.containsBean(autowiredBeanName) &&
                            beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                        cachedFieldValue = new ShortcutDependencyDescriptor(
                                desc, autowiredBeanName, field.getType());
                    }
                }
            }
            this.cachedFieldValue = cachedFieldValue;
            this.cached = true;
        }
    }
    return value;
}           
  • DefaultListableBeanFactory的解析依賴函數(構造器注入的循環依賴@Lazy解決點)
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 Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
    } else {
        // 對于構造器注入的循環依賴,添加@Lazy注解可以解決,下面一行代碼是解決的關鍵
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                descriptor, requestingBeanName);
        if (result == null) {
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}           
  • doResolveDependency是核心,真正解析依賴,這裡順便說一下,@Value注解,以及數組類型、Collection類型、Map類型的注入,@Autowired的注入解析邏輯都在這裡完成,根據不同的條件,運作對應的處理邏輯
    • 這裡解析@Autowired,先找到候選的bean,
    • 如果有多個bean,如:同一個接口存在多個實作類,根據@Primary決定候選的bean
    • 否則,直接取出候選的bean名稱和對應的類型instanceCandidate,
    • 對于還沒有在Spring Ioc容器中建立的依賴項,某屬性還沒有經過完整的生命周期,通過此步驟往單例緩存池中存入對應的bean(對應到源碼中的邏輯是:instanceCandidate instanceof Class判斷條件)
    • 【說明】:找候選的bean的函數findAutowireCandidates源碼,這裡暫時不展示,裡面的邏輯也值得研究。
@Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }

        Class<?> type = descriptor.getDependencyType();
        // 解析@Value注解
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                        getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            try {
                return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
            }
            catch (UnsupportedOperationException ex) {
                // A custom TypeConverter which does not support TypeDescriptor resolution...
                return (descriptor.getField() != null ?
                        converter.convertIfNecessary(value, type, descriptor.getField()) :
                        converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
            }
        }
        // 考慮屬性的不同情況:數組類型、Collection類型、Map類型
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }

        // 解析@Autowired依賴的多個bean,找到真正的候選bean
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        if (matchingBeans.size() > 1) {
            // 如果有多個bean,如:同一個接口存在多個實作類,根據@Primary決定候選的bean
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                }
                else {
                    // In case of an optional Collection/Map, silently ignore a non-unique case:
                    // possibly it was meant to be an empty collection of multiple regular beans
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        } else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        // 對于還沒有在Spring Ioc容器中建立的依賴項,如:orange屬性還沒有經過完整的生命周期,通過此步驟往單例緩存池中存入對應的bean
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}           
  1. 構造器注入的循環依賴
/*--------------------------- 示例代碼 ------------------------*/
@Component
public class A {

    private B b;

    // 如果是構造器循環依賴,加上Spring的@Lazy注解可以不報錯
    //@Lazy
    @Autowired
    public A(B b) {
        System.out.println("A的有參構造函數");
        this.b = b;
    }

    public void handleA() {
        System.out.println("調用A的handleA方法");
    }

}

@Component
public class B {

    private A a;

    @Autowired
    public B(A a) {
        System.out.println("B的有參構造函數");
    }

}           
  • 如果不加@Lazy注解,因為放入三級緩存的操作是在createBeanInstance執行個體化構造函數之後進行的,對于構造函數注入的循環依賴Spring無法解決,通過debug源碼得知,構造函數A依賴的b解析時,B又會調用a的執行個體化過程,在整個過程中,singletonFactories還沒來得及做remove操作,導緻getSingleton(String beanName, ObjectFactory<?> singletonFactory) 這個調用中,beforeSingletonCreation中singletonsCurrentlyInCreation對a的add操作不成功,導緻抛異常BeanCurrentlyInCreationException
  • 而如果加了@Lazy注解,解決的邏輯源碼在“DefaultListableBeanFactory的解析依賴函數”這一步,傳回的result不為空,直接傳回,不用運作重新擷取依賴屬性的操作,換句話說,A依賴的b,可以直接找到,A對象能順利完成初始化操作,不會抛異常
總結
  • Spring隻能解決屬性注入的循環依賴,無法解決構造器注入的循環依賴
  • 對于構造器注入的循環依賴,可通過加上@Lazy注解避免報錯