zoukankan      html  css  js  c++  java
  • 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集合中。

    至此,我们循环依赖已经结束,如有不明白的地方,可翻阅随笔中内容,如有其他疑问可留言或评论。

  • 相关阅读:
    laravel本地化
    laravel加载javascript库
    laravel安装第三方包3rd generators
    openfire的smack和asmack
    openfire+spark+smack实现即时通讯
    openfire开发
    即时通信Spark安装和配置
    ubuntu eclipse CDT 问题
    网络编程TCP总结及实践-C语言
    [Openstack]使用devstack自己主动化安装
  • 原文地址:https://www.cnblogs.com/daihang2366/p/15407328.html
Copyright © 2011-2022 走看看