转载

Spring5源码阅读--如何解决循环依赖?

首先要明确的是,循环依赖有以下几种:

  1. 构造函数的循环依赖。这种依赖显然是解决不了的。
  2. 非单例Bean的循环依赖。这种依赖也是解决不了的。
  3. 单例Bean的循环依赖。本文介绍的就是如何解决单例Bean的循环依赖的问题。

先来看一下测试代码,为了省略篇幅去掉setter和getter代码:

//Car.java
package beans;

public class Car {
    String name;
    Person person;
}

//Person.java
package beans;

public class Person {
    Car car;
    String name;
    int age;
}

//Test.java
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class Test {
    public static void main(String[] args) {
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));    //此行代码仅仅加载了配置文件,并且将里面的元素解析成BeanDefinition的形式,并添加到beanFactory中。此时并未创建bean。
        beanFactory.getBean("car");    //在第一次使用getBean()方法的时候会创建这个bean
    }
}

//beanFactoryTest.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="car" class="beans.Car">
        <property name="person" ref="person"/>
    </bean>
    <bean id="person" class="beans.Person">
        <property name="age" value="18"/>
        <property name="car" ref="car"/>
        <property name="name" value="SJ"/>
    </bean>

</beans>

在这里先简单说明一下, Test 类的 main() 函数中,第一行代码仅仅是加载xml文件里面的内容,生成若干个 BeanDefinition 类并添加到 BeanFactorybeanDefinitionMap 中,并未直接根据xml文件来创建定义的bean,而是留到第一次使用 getBean() 方法的时候才会创建这个bean以及它所依赖的对象,也就是懒加载模式。

那么就从 getBean() 来入手吧,之前需要注意一下 beanFactory 中几个与循环依赖相关的比较重要的字段,它们都定义在 DefaultSingletonBeanRegistry 类中:

/** Cache of singleton objects: bean name --> bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name --> bean instance */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Names of beans that are currently in creation */ private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

其中, singletonObjects 是用来保存已经注册的bean,里面的bean是已经初始化完成的;其他三个均用来保存正在创建但是还没完成创建的bean(比如正在创建A的同时发现A有一个属性值是B,于是把A摞一边先跑去初始化B了),可以理解为singleton对象的缓存池。但是它们三个也是有区别的,它们保存了不同创建阶段的singleton对象。很明显 singletonFactories 是一个bean name到bean工厂的映射,通过这个工厂可以得到对应name的bean,至于其它的区别会在下文慢慢讲解,诸位稍安勿躁。

下面开始分析 getBean() 函数,前面提到过,它才是bean初始化的起点。从现在起,假设所有的 BeanDefinition 已经被解析生成(本文中就定义了两个bean,Car和Person),但是还没有bean被初始化过,开始执行 Test 类的第二行。话不多说,放码过来,不过由于篇幅所限,将“无关”代码尽量删除一些:

//AbstractBeanFactory.java

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    (1)
    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); //标记1
        //如果从缓存中已经拿到了对象(先不管是从哪个缓存中拿到的),那就直接返回。
        if (sharedInstance != null && args == null) {
            //getObjectForBeanInstance()函数用来处理一个bean实现了FactoryBean接口的情况,在这种情况下,会调用这个bean的getObject()函数,并返回其结果。在本文的语境下,可以理解成这个函数什么都没做
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        //如果缓存中还没有对象,就新建一个
        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            //如果出现了prototype类型的循环依赖,直接抛出异常
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            //如果本BeanFactory中不包含beanName的定义,且有父BeanFactory,那么交给父BeanFactory去创建
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
          //下面两行代码从beanName得到对应的BeanDefinition并且转化成RootBeanDefinition类型,再并且如果有父bean的话需要和父bean的属性合并
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                //如果这个bean有dependsOn属性。切记,这个和我们今天要讲的循环依赖不是指同一个概念,这个是bean定义的dependsOn属性,我们今天要讲的是属性相互依赖,比如Car类包含了一个Person字段,Person类也包含了一个Car字段。不过两种循环依赖的解决方案都差不多,都是先转去创建依赖的bean,再回来创建自己。
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        getBean(dep);
                    }
                }

                // Create bean instance.
                if (mbd.isSingleton()) {
                    //如果bean的是单例
                    //标记2
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {                     
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                else if (mbd.isPrototype()) {
                    //如果bean的作用域是prototype,blabla...
                }
                else {
                    //如果是其它的作用域,blabla...
                }
        }

        // Check if required type matches the type of the actual bean instance.
        //这里检查类型是否匹配
        return (T) bean;
    }

在第一次调用 getBean() 的时候, singletonObjectssingletonFactories 等四个字段都是空的,再看一下方法(1)标记1处的 getSingleton() 的代码:

//DefaultSingletonBeanRegistry.java

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

    (2)
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        //isSingletonCurrentlyInCreation函数检测的是singletonsCurrentlyInCreation字段里有没有对应的bean,如果有,说明这个bean正在被创建
        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();  //标记1
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

由于此时几个字段都为空,所以方法(2)直接返回null。再回到方法(1),下一个比较重要的方法是方法(1)标记2处的代码,此时 getSingleton() 代码如下:

//DefaultSingletonBeanRegistry.java
    (3)
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                //下面一行代码把这个bean加入singletonsCurrentlyInCreation字段中
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;

                try {
                    //调用getObject()方法创建对象!!真正创建对象的过程以及对循环依赖的递归处理就在这个函数中!!所以当这个函数返回的时候,这个bean已经被创建完成,它所依赖的bean也已经被创建完成!!如果暂时有什么不理解的,可以先记住结论,再看看后面的流程。
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                finally {
                    //创建完成,把bean从singletonsCurrentlyInCreation中移除
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    //此时才把bean加入singletonObjects字段中,所以singletonObjects字段中都是已经创建完成的bean
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

传递给方法(3)的参数是在方法(1)的标记2处 createBean(beanName, mbd, args) ,进入这个函数:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
        //真正开始创建bean的实例
        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        //处理需要覆盖的方法,对应<bean>标签的<lookup-method>和<replace-method>属性
        try {
            mbdToUse.prepareMethodOverrides();
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            //此时会调用注册的InstantiationAwareBeanPostProcessor类的postProcessBeforeInstantiation方法来实现一些代理之类的功能。在本文的语境中可以认为bean == null。
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {   //如果bean不为null,直接返回,不进行正常的创建流程
                return bean;
            }
        }   
        try {
            //doCreateBean函数返回时代表bean已经创建完毕
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
    }

再来看一下 doCreateBean() 函数,这个函数先构造的是一个 BeanWrapper 类的对象,包装了对应的bean,然后再调用 BeanWrapper.getWrappedInstance() 方法得到被包装的bean:

//AbstractAutowireCapableBeanFactory.java
    (4)
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //在这里创建BeanWrapper对象,但是此时并没有注入属性值
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //得到BeanWrapper包装的bean
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        //调用MergedBeanDefinitionPostProcessor后处理器的函数
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }           
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        //判断是否需要提早将bean放入缓存,接下来进行的populateBean()方法可能会产生循环依赖问题,所以需要此时就把未完成的bean放入缓存
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            //这里是第一次调用getBean()方法来得到这个bean,把这个bean放入BeanFactory的singletonFactories字段中
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //填充bean的属性值,如果有依赖的属性也是一个bean,就先去创建那个bean
            populateBean(beanName, mbd, instanceWrapper);
            //调用初始化方法,比如init-method,另外如果这个bean实现了一些Aware接口,比如BeanFactoryAware,也在这个方法里面调用了接口的相应函数对bean进行处理
            exposedObject = initializeBean(beanName, exposedObject, mbd);  //标记1
        }

        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 " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }



        return exposedObject;
    }

由于循环依赖问题是在 populateBean() 函数中完成的,来看一下这个函数的代码:

//AbstractAutowireCapableBeanFactory.java

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable  BeanWrapper bw) {

        // 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.
        boolean continueWithPropertyPopulation = true;
        //在属性值注入之前给InstantiationAwareBeanPostProcessor一次机会设置属性值
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    //返回值为false会阻止其它的InstantiationAwareBeanPostProcessor再设置属性值,并且会导致不再给这个bean填充属性
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

        //获得BeanDefinition中收集到的属性值
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
        //由于在本例中我们直接使用的xml的<property>标签,所以mbd.getResolvedAutowireMode() = 0,这一段被跳过。不过实际中,autowireByName和autowireByType也会导致bean的递归创建,因为它们内部也会调用getBean()函数来获取另一个bean
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            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;
        }

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

是了,设置属性值其实是在 applyPropertyValues 函数中:

//AbstractAutowireCapableBeanFactory.java
(5)
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if (pvs.isEmpty()) {
            return;
        }

        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;

        if (pvs instanceof MutablePropertyValues) {
            mpvs = (MutablePropertyValues) pvs;
            if (mpvs.isConverted()) {
                // Shortcut: use the pre-converted values as-is.
                try {
                    bw.setPropertyValues(mpvs);
                    return;
                }   
            }
            original = mpvs.getPropertyValueList();
        }
        else {
            original = Arrays.asList(pvs.getPropertyValues());
        }

        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
        //获取属性值解析器
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

        // Create a deep copy, resolving any references for values.
        List<PropertyValue> deepCopy = new ArrayList<>(original.size());
        boolean resolveNecessary = false;
        for (PropertyValue pv : original) {
            if (pv.isConverted()) {
                deepCopy.add(pv);
            }
            else {
                String propertyName = pv.getName();
                Object originalValue = pv.getValue();
                //在这个函数中把对应ref值的bean解析成一个真实的bean,换名话说,在这个函数里面调用了getBean()方法
                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                Object convertedValue = resolvedValue;
                boolean convertible = bw.isWritableProperty(propertyName) &&
                        !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                if (convertible) {
                    convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
                }
                // Possibly store converted value in merged bean definition,
                // in order to avoid re-conversion for every created bean instance.
                if (resolvedValue == originalValue) {
                    if (convertible) {
                        pv.setConvertedValue(convertedValue);
                    }
                    deepCopy.add(pv);
                }
                else if (convertible && originalValue instanceof TypedStringValue &&
                        !((TypedStringValue) originalValue).isDynamic() &&
                        !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                    pv.setConvertedValue(convertedValue);
                    deepCopy.add(pv);
                }
                else {
                    resolveNecessary = true;
                    deepCopy.add(new PropertyValue(pv, convertedValue));
                }
            }
        }
        if (mpvs != null && !resolveNecessary) {
            mpvs.setConverted();
        }

        // Set our (possibly massaged) deep copy.
        try {
            //设置属性值
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        }
    }

其中 resolveValueIfNecessary 方法中又根据属性值的类型采取了不同的解析逻辑,其中在 <property> 标签的 ref 值对应的逻辑是调用 resolveReference 方法,就是在这个方法中调用了 getBean() 方法来完成对依赖的处理。至此,总结一下, car 对象的初始化还未完成,需要调用 getBean(person) 方法来得到 person 对象,然后才能把 person 对象注入设置成 car 对象的属性。到目前为止, car 对象已经把自己加入到了 singletonFactories 缓存中(确切地说是把得到自己的方法加入到了缓存中)。

接下来是 getBean("person") 的过程,和 getBean("car") 很类似,一路到了方法(5)这里,同样需要设置 person 对象的属性值,于是接下来又产生了 getBean("car") 的调用,不过此次是 getBean("car") 的第二次调用了,来看一下和第一次有什么不同的地方。

在方法(1)的标记1处,此时缓存中已经有了 car 这个bean,于是在方法(2)的标记1处调用了 car 对应的工厂函数,在这个函数中得到缓存的 car ,并且将其加入到另一个缓存 earlySingletonObjects 中,并将其工厂函数从缓存 singletonFactories 中删除。然后回到方法(1)的流程,得到缓存中的对象后,就不必再去从头创建,直接进行 getObjectForBeanInstance 的调用(前面说过这个函数只是用于处理FactoryBean接口的对象),然后再进行一下类型检查就可以直接返回给 person 了。最后在 person 的方法(5)中将其做为一个属性设置给 person 。至此, person 的创建完成,返回给 car 的方法(5)。不过在返回之前,在方法(4)的标记1处,调用了 initializeBean() 方法,在里面调用了bean的初始化函数和后处理器的方法。之后又在方法(3)中把 personsingletonsCurrentlyInCreationearlySingletonObjects 中删除,并且把 person 加入到 singletonObjects 缓存中,下次再调用 getBean("person") 的时候就可以直接从 singletonObjects 缓存中取得。

person 返回给 car 的方法(5)之后,也是同样的流程,调用初始化方法和后处理器的方法,然后把 car 加入永久缓存 singletonObjects 中,并从临时缓存 earlySingletonObjects 中删除,至此,两个有循环依赖关系的bean都被初始化完毕。

原文  http://blog.csdn.net/Q_AN1314/article/details/79613214
正文到此结束
Loading...