Spring源码分析——循环依赖解决流程跟进

44 阅读6分钟

1、三级缓存

一级缓存(singletonObject):存储的是所有创建好了的单例Bean

二级缓存(earlySingletonObjects):完成实例化,但是还未进行属性注入及初始化的对象

三级缓存(singletonFactories):提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象

1.1、demo

package org.example.dependOn;

/**
 * ---leetcode---
 *
 * @author summer77
 * @date 2024/2/28 17:35
 * <p>
 * ---Demo1---
 */
public class Demo1 {
    public Demo2 demo2;
    

    public void setDemo2(Demo2 demo2) {
        this.demo2 = demo2;
    }

    public Demo2 getDemo2() {
        return demo2;
    }
}
package org.example.dependOn;

/**
 * ---leetcode---
 *
 * @author summer77
 * @date 2024/2/28 17:35
 * <p>
 * ---Demo2---
 */
public class Demo2 {
    public Demo1 demo1;

    public Demo1 getDemo1() {
        return demo1;
    }

    public void setDemo1(Demo1 demo1) {
        this.demo1 = demo1;
    }
}
package org.example.dependOn;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * ---leetcode---
 *
 * @author summer77
 * @date 2024/2/28 17:35
 * <p>
 * ---MyTest---
 */
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("a05.xml");

        Demo1 demo1 = (Demo1) context.getBean("demo1");
        Demo2 demo2 = (Demo2) context.getBean("demo2");

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

    <bean id="demo1" class="org.example.dependOn.Demo1">
        <property name="demo2" ref="demo2"/>
    </bean>

    <bean id="demo2" class="org.example.dependOn.Demo2">
        <property name="demo1" ref="demo1"/>
    </bean>
</beans>

1.2、源码剖析

  • 直接看bean1创建时,在注入bean2前的处理
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }

    if (instanceWrapper == null) {
        // 在这里完成了无参/有参构造
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    // 获取到完成构造的Bean,此时还未进行属性注入
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    synchronized(mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            } catch (Throwable var17) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
            }

            mbd.postProcessed = true;
        }
    }
    
    // 关键在这里,如果当前Bean是单例且允许循环依赖且正在创建中
    boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    
    // 那么他需要早期暴露
    if (earlySingletonExposure) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
        }
        
        // 我们看这里面
        this.addSingletonFactory(beanName, () -> {
            return this.getEarlyBeanReference(beanName, mbd, bean);
        });
    }

    Object exposedObject = bean;

    try {
        // 属性注入阶段
        this.populateBean(beanName, mbd, instanceWrapper);
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
            throw (BeanCreationException)var18;
        }

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = this.getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                String[] dependentBeans = this.getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                String[] var12 = dependentBeans;
                int var13 = dependentBeans.length;

                for(int var14 = 0; var14 < var13; ++var14) {
                    String dependentBean = var12[var14];
                    if (!this.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.");
                }
            }
        }
    }

    try {
        this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
        return exposedObject;
    } catch (BeanDefinitionValidationException var16) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
    }
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    SmartInstantiationAwareBeanPostProcessor bp;
    
    // 这个检查条件是不是很熟悉,AOP中见过,他的目的是检查这个bean是不是该被代理
    if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
        for(Iterator var5 = this.getBeanPostProcessorCache().smartInstantiationAware.iterator(); var5.hasNext(); exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)) {
            bp = (SmartInstantiationAwareBeanPostProcessor)var5.next();
        }
    }
    
    // 如果不是动态代理Bean,那就直接返回原Bean了
    // 如果是,需要先生成动态代理Bean
    return exposedObject;
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized(this.singletonObjects) {
        // 一级缓存,存放完全创建好的Bean
        // 确保Bean还没有进行属性注入
        if (!this.singletonObjects.containsKey(beanName)) {
            // 放入三级缓存
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }

    }
}
  • 此时bean1放入了三级缓存,接着在populateBean()开始对Bean1的属性注入,然后一路追到解析引用的地方
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
    try {
        // 获取Bean2的类类型
        Class<?> beanType = ref.getBeanType();
        Object bean;
        // 判断这个Bean2是不是来自父工厂
        // 如果来自父工厂就从父工厂中getBean()
        if (ref.isToParent()) {
            BeanFactory parent = this.beanFactory.getParentBeanFactory();
            if (parent == null) {
                throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available");
            }

            if (beanType != null) {
                bean = parent.getBean(beanType);
            } else {
                bean = parent.getBean(String.valueOf(this.doEvaluate(ref.getBeanName())));
            }
        } else {
            // 不是父工厂的Bean
            String resolvedName;
            if (beanType != null) {
                NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
                bean = namedBean.getBeanInstance();
                resolvedName = namedBean.getBeanName();
            } else {
                resolvedName = String.valueOf(this.doEvaluate(ref.getBeanName()));
                
                // 进行bean2的getBean
                bean = this.beanFactory.getBean(resolvedName);
            }

            this.beanFactory.registerDependentBean(resolvedName, this.beanName);
        }

        if (bean instanceof NullBean) {
            bean = null;
        }

        return bean;
    } catch (BeansException var7) {
        throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var7);
    }
}
  • bean2此时还只是注册了BeanDefinition,三级缓存中都没有bean2,所以要进行bean2的初始化了,所以将进行bean2的createBean()

  • 接下来的流程可以预料到,Bean2照常进行他的构造初始化,然后又被发现是个需要早期暴露的Bean,将其放入了三级缓存中

  • 再然后bean2也进入了populateBean()方法中,他又要注入bean1,又回到了刚刚的方法。循环依赖产生了

@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {

            // getBean("bean1")
            bean = this.beanFactory.getBean(resolvedName);
}

  • 又进入了对bean1的getBean(),因为有三级缓存的作用,这次会不太一样
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    Object sharedInstance = this.getSingleton(beanName);
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从一级缓存中拿已经完全创建好的bean1,现在自然是拿不到的 获取到的是NULL
    Object singletonObject = this.singletonObjects.get(beanName);
    
    // isSingletonCurrentlyInCreation 前面将bean1放入了这个表示bean正在创建的集合中
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
    
        // 所以我们这次进入到了这里
        // 此时二级缓存中也是没有bean1的,获取到的是NULL
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            synchronized(this.singletonObjects) {
                
                //再次确认一级缓存中没有bean1
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                
                    //再次确认二级缓存中没有bean1
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                    
                        // 然后成功进入到了这里
                        // 这次是有的,在bean完成无参构造后检查到需要提前暴露,三级缓存放入了一个提前暴露的单例工厂,里面存放了bean1
                        ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            // 获取到bean1
                            singletonObject = singletonFactory.getObject();
                            // 将bean1放入二级缓存中
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            // 移除三级缓存中的信息
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    // 最终返回了只进行了构造初始化的bean1
    return singletonObject;
}
String beanName = this.transformedBeanName(name);

// 这次sharedInstance终于不为NULL了
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;

//中间的代码题主跑了一通发现什么都没有发生,最终返回了bean1
return this.adaptBeanInstance(name, beanInstance, requiredType);

· 现在,bean2拿到了还没完成属性注入的bean1,我们回到resolveReference()方法

@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
    try {
        Class<?> beanType = ref.getBeanType();
        Object bean;
        if (ref.isToParent()) {
            BeanFactory parent = this.beanFactory.getParentBeanFactory();
            if (parent == null) {
                throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available");
            }

            if (beanType != null) {
                bean = parent.getBean(beanType);
            } else {
                bean = parent.getBean(String.valueOf(this.doEvaluate(ref.getBeanName())));
            }
        } else {
            String resolvedName;
            if (beanType != null) {
                NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
                bean = namedBean.getBeanInstance();
                resolvedName = namedBean.getBeanName();
            } else {
                resolvedName = String.valueOf(this.doEvaluate(ref.getBeanName()));
                
                // 拿到了bean1
                bean = this.beanFactory.getBean(resolvedName);
            }
            
            // 注册
            this.beanFactory.registerDependentBean(resolvedName, this.beanName);
        }

        if (bean instanceof NullBean) {
            bean = null;
        }
        
        // 最终返回了bean1
        return bean;
    } catch (BeansException var7) {
        throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var7);
    }
}
  • 然后就是将bean1注入到bean2当中,bean2的属性注入就可以正常完成了,bean2被完整的创建了出来
  • 然后再回到bean1的属性注入,bean1也获得了完全创建的bean2,此时bean1也可以正常的完成属性注入了,bean1也被完整的创建了出来
  • 最后,二三级缓存的相关数据都会清掉,在一级缓存中放入完全创建好的Bean