1. 程式人生 > 其它 >Spring迴圈依賴原理

Spring迴圈依賴原理

1、現象概述

這個現象其實大部分都知道,迴圈依賴也是網上比較流傳Spring的一個問題。

比如現在有一個類為Class1,然後其有一個屬性為Class2,然後Class2這個類裡有一個屬性為Class1。當這兩個類都是單例的時候,就存在迴圈依賴的問題了。

那麼這種情況在Spring管理Bean的時候是如何解決的呢?

下面來描述

2、程式碼現象

Class1.java

@Component
public class Class1 {
	@Autowired
	private Class2 class2;
}

Class2.java

@Component
public class Class2 {
	@Autowired
	private Class1 class1;
}

用容器去獲取getBean

看我們的Class1,它的屬性class2有值,其Class2的屬性class1也有值,這就是迴圈依賴,下面我們來解釋Spring如何解決這個問題。

3、大概解釋

在看原始碼之前,我們先用白話文對其進行解釋。

首先我們Spring先去走Class1的生命週期,首先是用構造器建立Class1的物件,在建立結束以後,對Class1的屬性進行注入,在注入Class2的時候,實際上是去呼叫getBean(Class2),然後Class2在建立結束以後,又回去注入Class2中的class1屬性,那麼自然就會去呼叫getBean(Class1),此時去getBean(Class1)是能獲取到的,但注意次數獲取道德Class1屬性並未注入完成,那麼這樣Class2的class1屬性就注入完成,就回到了Class1注入class2的時候,這時Class1去getBean(Class2)就完成,注意此時Class2已經注入完成,那麼就將Class2注入到Class1的class2屬性中,至此,迴圈依賴就結束。

你可能有如下疑問:

​ Class1注入Class2的時候,是如何去getBean的?

​ Class2注入Class1的時候,為什麼getBean能獲取到Class1,具體程式碼在哪裡判斷的?為什麼獲取到Class1屬性並未注入完成?

下面原始碼解析中一一解釋。

4、原始碼解析

來到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean中:

在進入這個方法之前,先展示方法棧:

好,現在進入方法程式碼:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			/**
			 * 這裡實際上是去建立Bean了,
			 * 此類中屬性並未賦值,比如@Autowried
			 *
			 * */
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		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 {
					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.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			/**
			 * 最主要是的將當前建立好的Bean放置到singletonFactories的Map中
			 * */
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			/* 填充Bean,填充其屬性的值 */
			populateBean(beanName, mbd, instanceWrapper);
			/**
			 * 去執行
			 * 	BeanPostProcessor的postProcessBeforeInitialization方法
			 * */
			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);
			}
		}
		.......省略程式碼
		return exposedObject;
	}

此時我們的beanName為“class1”。

我們分段看:

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
    mbd.resolvedTargetType = beanType;
}

這裡createBeanInstance是去建立類的例項,這個建立的例項當前是啥也沒有的,屬性並未填充。

// 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.isDebugEnabled()) {
        logger.debug("Eagerly caching bean '" + beanName +
                     "' to allow for resolving potential circular references");
    }
    /**
			 * 最主要是的將當前建立好的Bean放置到singletonFactories的Map中
			 * */
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

addSingletonFactory這個方法最主要的就是將我們剛剛建立的例項加入到singletonFactories這個Map當中去,這個map在迴圈依賴裡面很重要,注意這個Map中的Class1是才建立好的,並沒有屬性注入。

// Initialize the bean instance.
Object exposedObject = bean;
try {
    
    populateBean(beanName, mbd, instanceWrapper);

    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);
    }
}

這裡面populateBean是完成屬性注入(換個叫法就是完成Bean填充),initializeBean是執行BeanPostProcessor的回撥,我們關心populateBean方法。

進入populateBena方法中。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

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 (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                if (!ibp.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);

    if (hasInstAwareBpps || needsDepCheck) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        /**
		* 拿到所有的get/set方法
		* */
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    /**
						 * 重點看這個PostProcess:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
						 * 這個是去處理自動注入的.
						 * */
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }

    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }

分段看:

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;
    }
}

判空處理,這個沒什麼好解釋。

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }
}

InstantiationAwareBeanPostProcessor的方法postProcessAfterInstantiation,該方法的返回值是boolean,如果返回true,則什麼都不幹,如果返回false,那麼此類則不會進行自動裝配(屬性填充),這裡就是可以讓我們通過postprocessor的方式控制某些bean不用屬性填充。這裡很明顯如果我們沒做特殊處理,這裡最裡面的if的return是不會被執行到的。

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;
}

resolvedAutowireMode:自動注入模型,預設為AUTOWIRE_CONSTRUCTOR,所以這裡不會進if,如果該BeanDefinition的注入模型是這兩種的,那麼則分別的可以嘗試byType方式,byName方式。

    /**
		 * 要不要處理
		 * */
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    /**
		 * 要不要深度檢查
		 */
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

這兩個屬性註釋上有,很明顯都為true。

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        /**
		* 重點看這個PostProcess:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
		* 這個是去處理自動注入的.
		 * */
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
        if (pvs == null) {
            return;
        }
    }
}

屬性注入是使用BeanPostProcessor來完成的。

這裡是使用BeanPostProcessor的子類InstantiationAwareBeanPostProcessor來完成屬性注入,這裡面很多InstantiationAwareBeanPostProcessor,我們主要關心AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法,我們進入AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法來看。

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

@Override
public PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    /**
	* 拿到需要注入的欄位,這個方法不需要去深究
	* */
    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 metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);

這個是去獲取到當前類中需要注入的屬性,注意此時beanName為前面說到的class1,bean.getClass()為Class1。

我們來斷點看看當前的metadata中是否包含了我們Class1中需要注入的class2屬性。

那麼我們進入metadata.inject方法。

org.springframework.beans.factory.annotation.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) {
            if (logger.isDebugEnabled()) {
                logger.debug("Processing injected element of bean '" + beanName + "': " + element);
            }
            /**
			* 對屬性進行注入操作,當前的element是需要被注入的欄位,target是原類的例項物件,beanName是bean的名稱,是target的類名稱
			* 注意,這個Element為:AutowiredFieldElement
			* */
            element.inject(target, beanName, pvs);
        }
    }
}

將剛才找到的所有需要注入的屬性遍歷給注入。

我們進入element.inject方法,注意此時的target為Class1,beanName為class1。

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
   
    Object value;
    if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    else {
        /**
		* 可以理解為欄位的描述
		*/
        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();
        try {
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        synchronized (this) {
            if (!this.cached) {
                if (value != null || this.required) {
                    this.cachedFieldValue = desc;
                    registerDependentBeans(beanName, autowiredBeanNames);
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        if (beanFactory.containsBean(autowiredBeanName) &&
                            beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                            this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                desc, autowiredBeanName, field.getType());
                        }
                    }
                }
                else {
                    this.cachedFieldValue = null;
                }
                this.cached = true;
            }
        }
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

分段看:

Object value;

這個value就是用來存放例項化出來以後的Class2物件。

value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

此處就是去getBean(Class2),然後再將拿到的value設定到Class1的class2屬性當中去。

  if (value != null) {
      ReflectionUtils.makeAccessible(field);
      field.set(bean, value);
  }

設定到Class1的class2屬性中去。

我們現在來看beanFactory.resolveDependency方法。

org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency

@Override
@Nullable
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 {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
        if (result == null) {
            /**
				 * 例項化
				 *  */
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

如果我們的欄位型別是這些指定的某個class型別,那麼則特殊處理,如果都不是,則else裡面進行處理。

我們這裡直不是特殊的型別,直接進入doResolveDependency。

org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                                  @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    .....省略
        if (instanceCandidate instanceof Class) {
            /**
			* 去使用beanFactory.getBean去建立這個屬性的Bean
			* */
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
    .....省略
        return result;
}
finally {
    ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}

上下的程式碼都根本次的迴圈依賴沒關係,我們重點看這個if裡面的。

注意此時的autowiredBeanName為:class2,此時的type為:com.dh.pojo.Class2,此時的this為:BeanFactory。

現在進入descriptor.resolveCandidate方法:

org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
			throws BeansException {

    return beanFactory.getBean(beanName);
}

這裡可以看到,其實是去beanFactory中呼叫getBean方法。

到達org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean方法中。

我們這裡快速的過去,不去細究這個例如建立的Class2:

到達org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中:

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

		。。。。省略
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			/* 填充Bean,填充其屬性的值 */
			populateBean(beanName, mbd, instanceWrapper);
			/**
			 * 去執行
			 * 	BeanPostProcessor的postProcessBeforeInitialization方法
			 * */
			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);
			}
		}

		。。。。省略
		return exposedObject;
	}

注意現在這個時候,beanName為class2。

進入populateBean方法後我們再次進入org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues方法中。

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
		/**
		 * 拿到需要注入的欄位,這個方法不需要去深究
		 * */
		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;
	}

再次進入metadata.inject方法,org.springframework.beans.factory.annotation.InjectionMetadata#inject

org.springframework.beans.factory.annotation.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) {
				if (logger.isDebugEnabled()) {
					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
				}
				/**
				 * 對屬性進行注入操作,當前的element是需要被注入的欄位,target是原類的例項物件,beanName是bean的名稱,是target的類名稱
				 * 注意,這個Element為:AutowiredFieldElement
				 * */
				element.inject(target, beanName, pvs);
			}
		}
	}

注意此時的target為Class2,beanName為class2,此時是需要去注入Class2中的class1屬性的。

那麼此時我們跳躍一下程式碼,中間的都不是關鍵,到達org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean中來。

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		/* 此處需要處理FactoryBean的情況,如果是FactoryBean的話,此處的BeanName為&xxxx,此處需要將&去掉 */
		String beanName = transformedBeanName(name);
		Object bean;

		/*
		* 去當前容器中獲取例項化好的Bean,如果bean不為空,則直接返回了,如果為空,則需要去例項化,進入else
		*  */
		// 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省略
		return (T) bean;
	}

注意此時的beanName為“class1”,然後注意Object sharedInstance = getSingleton(beanName);中得到的sharedInstance不為空,這裡很重要,是解決迴圈依賴最重要的位置。你如果細心可以發現,在第一次Class1進入doGetBean的時候,這裡的getSingleton結果為空,第二次Class2進入doGetBean的時候,這裡的getSingleton結果也是空,第三次Class1進入doGetBean的時候,getSingleton結果不是空了。

那麼這裡可以看到如果sharedInstance不為空的話,就不會進入else,else裡面是進行建立bean的程式碼,if裡面的話,就會在後面直接return這個bean。

那麼這裡我們大概就知道了,來理一下,

​ 1、第一次Class1建立的時候,getSingleton為空那麼建立物件。

​ 2、Class1注入Class2,那麼Class2這裡getSingleton為空,那麼則建立物件。

​ 3、Class2注入Class1的時候,這裡Class1的getSingleton不為空,那麼Class2就成功的注入得到了Class1。

​ 4、當Class2注入完成Class1以後,就回到了Class1注入Class2的位置,這個時候Class1已經成功拿到了Class2,那麼就將其注入到Class1自己的屬性裡面去。

至此迴圈依賴就解決了。

但是需要注意,當3步的時候,Class1的getSingleton得到的物件中,其屬性並未注入完成。

那麼就代表這個時候拿到的Class1就是一個未填充完成的物件。

但是這種方式是可以解決迴圈依賴的問題的。

那麼這裡我們有一些問題還沒有解決:

​ 1、getSingleton為什麼能拿到Class1

​ 2、有人可能聽說過,是快取,說白了這個快取就是一個Map,存放臨時的Class1,那麼這個Map是哪個呢,臨時的Class1是何時存入Map中的呢?

首先我們來看getSingleton方法怎麼獲取到Class1的:

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)

	@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

再次進入getSingleton方法。

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

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;
}

首先this.singletonObjects.get(beanName)結果肯定為空,因為這個singletonObjects集合中存放的是已經走過完整生命週期的Bean,很明顯我們這裡的Class1並沒有。

那麼下面的這個if會進入,singletonObjects為空這個true我們知道,我們來看看isSingletonCurrentlyInCreation(beanName),注意此時的beanName為class1。

public boolean isSingletonCurrentlyInCreation(String beanName) {
    return this.singletonsCurrentlyInCreation.contains(beanName);
}

注意此時的singletonsCurrentlyInCreation裡面的元素為:

這個集合代表著,當前正在建立的物件,此時我們的Class1和Class2在這裡面。

那麼自然這個if就能進去了。

然後注意看if裡面singletonObject = this.earlySingletonObjects.get(beanName);

這個時候獲取的仍然是空的。但是下一行中this.singletonFactories.get(beanName)裡面就不是空了

這裡可以看得到,成功的拿出了Class1這個物件,且裡面的class2屬性為空的。

那麼我們這裡就看明白整體了。我這裡再描述一遍。

1、建立Class1物件,並將其beanName放置到singletonsCurrentlyInCreation集合中、singletonFactories集合中。

2、注入Class1中的class2,這時需要去建立Class2,並將其Class2的beanName放置到singletonsCurrentlyInCreation集合中、singletonFactories集合中。

3、再對Class2進行注入class1屬性,這時getSingleton方法中就能拿到Class1這個物件,那麼getSingleton中首先判斷當前Class1是否在singletonsCurrentlyInCreation集合中,如果在,那麼就從singletonFactories集合中將其取出。

那麼我們最後再來看一個東西,看Spring在何時將beanName存放至singletonsCurrentlyInCreation集合中,何時將建立好的物件存放至singletonFactories中。

進入到:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

注意看這個方法,beforeSingletonCreation,進入這個方法。

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#beforeSingletonCreation

protected void beforeSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

注意看這裡將當前的beanName存放至singletonsCurrentlyInCreation集合當中去,這裡我們找到了在哪裡存放到singletonsCurrentlyInCreation集合中去的。

注意這個getSingleton方法中會去呼叫doCreateBean方法。

然後我們再來找何時存放至singletonFactories集合中的,注意這個Map的value是一個物件,那麼代表是在我們Bean建立完以後才存放至這個集合中的。

進入到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

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);
        }
    }
}

這裡的!this.singletonObjects.containsKey(beanName)其實就是當前Bean如果沒有走完生命週期的話,就會進入這個IF,因為singletonObjects集合中是存放已經走完生命週期的。

然後下面就是將當前的Bean加入到singletonFactories集合中。

至此,我們迴圈依賴已經結束,如有不明白的地方,可翻閱隨筆中內容,如有其他疑問可留言或評論。