Spring循环依赖

1,298 阅读13分钟

一、循环依赖介绍

1.1 什么是循环依赖?

类A依赖类B,类B也依赖类A。像这样类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。

1.2 Spring中主要有哪几种循环依赖问题?

  • 通过构造方法进行依赖注入时产生的循环依赖问题。
  • 通过setter方法进行依赖注入且是在多例(原型)模式下产生的循环依赖问题。
  • 通过setter方法进行依赖注入且是在单例模式下产生的循环依赖问题。

注意: 在Spring中,只有【第三种方式】的循环依赖问题被解决了,其他两种方式在遇到循环依赖问题时都会产生异常。

二、Spring怎么解决循环依赖的?

  • singletonObjects:一级缓存,存放**完全初始化好的Bean(填充属性完成,初始化完成)**的集合,从这个集合中取出来的Bean可以立马返回
  • earlySingletonObjects:二级缓存,存放**半成品的单实例Bean(已实例化但未注入属性和初始化)**的集合,它用来解决循环依赖
  • singletonFactories:三级缓存,存放**Bean工厂对象(仅仅只实例化完成)**的集合
  • singletonsCurrentlyInCreation:存放正在被创建的Bean的集合

Spring解决循环依赖的核心思想在于提前曝光:

  1. 通过构建函数创建A对象(A对象是半成品,还没注入属性和调用init方法)。
  2. A对象需要注入B对象,发现缓存里还没有B对象,将半成品对象A放入半成品缓存。
  3. 通过构建函数创建B对象(B对象是半成品,还没注入属性和调用init方法)。
  4. B对象需要注入A对象,从半成品缓存里取到半成品对象A。
  5. B对象继续注入其他属性和初始化,之后将完成品B对象放入完成品缓存。
  6. A对象继续注入属性,从完成品缓存中取到完成品B对象并注入。
  7. A对象继续注入其他属性和初始化,之后将完成品A对象放入完成品缓存。

spring三级缓存.png

2.1 伪代码:

初始化方法

public interface SmallInitializingBean {

    void afterPropertiesSet();
}

Object工厂

@FunctionalInterface
public interface SmallObjectFactory<T> {

    T getObject() throws BeansException;

}

创建Bean方法

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class SmallAbstractBeanFactory {

    // 一级缓存
    private static final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //一级缓存
    // 二级缓存
    private static final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    // 三级缓存
    private static final Map<String, SmallObjectFactory<?>> singletonFactories = new HashMap<>(16);
    //正在创建的Bean
    private static final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));


    public static <T> T getBean(String name,Class<T> requiredType){

        Object bean = getSingleton(name, true);

        if (bean == null ){
            bean = doCreateBean(name,requiredType);
        }


        return (T) bean;
    }

    protected static Object doCreateBean(String beanName,Class cls) {

        singletonsCurrentlyInCreation.add(beanName);

        //第一步、实例化Bean
        Object bean = createBeanInstance(beanName,cls);

        //第二步、放入三级缓存
        addSingletonFactory(beanName,() -> getEarlyBeanReference(beanName,bean));

        //第三步、赋值属性
        populateBean(beanName,bean);

        //第四步、初始化Bean
        initializeBean(bean);

        //第五步、 代理等 ----


        singletonsCurrentlyInCreation.remove(beanName);
        //最后添加进单例缓存
        addSingleton(beanName,bean);
        return bean;
    }

    private static Object createBeanInstance(String beanName, Class cls) {
        Object ins = null;
        try {
            ins = cls.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ins;
    }

    protected static void addSingletonFactory(String beanName, SmallObjectFactory<?> singletonFactory) {
        System.out.println("第二步:放入三级缓存   "+beanName);
        synchronized (singletonObjects) {
            if (!singletonObjects.containsKey(beanName)) {
                singletonFactories.put(beanName, singletonFactory);
                earlySingletonObjects.remove(beanName);
            }
        }
    }

    protected static void populateBean(String beanName,Object bean){
        System.out.println("第三步:属性赋值   SmallStudent");

        //这里赋值只是举例,真正Spring在赋值的时候会有很多操作:名称注入 类型注入 @Resource、@Autowired、@Value自动注入等
        if ("smallTeacher".equals(beanName)){
            ((SmallTeacher)bean).setName("教师");
            ((SmallTeacher) bean).setStudent(getBean("smallStudent",SmallStudent.class));
        }

        if ("smallStudent".equals(beanName)){
            ((SmallStudent)bean).setName("学生");
            ((SmallStudent)bean).setTeacher(getBean("smallTeacher",SmallTeacher.class));
        }
    }

    protected static Object initializeBean(Object bean){

        //做一些初始化操作
        //例如:
        if (bean instanceof SmallInitializingBean){
            ((SmallInitializingBean)bean).afterPropertiesSet();
        }
        return bean;
    }

    protected static Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                synchronized (singletonObjects) {
                    // Consistent creation of early reference within full singleton lock
                    singletonObject = singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            SmallObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                earlySingletonObjects.put(beanName, singletonObject);
                                singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }
        return singletonObject;
    }

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

    protected static Object getEarlyBeanReference(String beanName, Object bean) {
        Object exposedObject = bean;
        System.out.println("做一次早期代理判断:是否需要创建代理对象");
        return exposedObject;
    }

    protected static void addSingleton(String beanName, Object singletonObject) {
        synchronized (singletonObjects) {
            singletonObjects.put(beanName, singletonObject);
            singletonFactories.remove(beanName);
            earlySingletonObjects.remove(beanName);
        }
    }
}

测试类

public class SmallStudent implements SmallInitializingBean{

    private String name;

    private SmallTeacher teacher;

    public SmallStudent() {
        System.out.println("第一步:实例化Bean   SmallStudent");
    }

    @Override
    public void afterPropertiesSet(){
        System.out.println("第四步:执行初始化方法   SmallStudent");
    }

    public SmallTeacher getTeacher() {
        return teacher;
    }

    public void setTeacher(SmallTeacher teacher) {
        this.teacher = teacher;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "SmallStudent{" +
                "name='" + name + ''' +
                ", teacher=" + teacher.getName() +
                '}';
    }
}
public class SmallTeacher implements SmallInitializingBean{

    private String name;

    private SmallStudent student;

    public SmallTeacher() {
        System.out.println("第一步:实例化Bean   SmallTeacher");
    }

    @Override
    public void afterPropertiesSet(){
        System.out.println("第四步:执行初始化方法   SmallTeacher");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public SmallStudent getStudent() {
        return student;
    }

    public void setStudent(SmallStudent student) {
        this.student = student;
    }

    @Override
    public String toString() {
        return "SmallTeacher{" +
                "name='" + name + ''' +
                ", student=" + student.getName() +
                '}';
    }
}

执行测试结果

public class SmallTest {
    public static void main(String[] args) {
        Object student = SmallAbstractBeanFactory.getBean("smallStudent",SmallStudent.class);
        System.out.println(student.toString());
        Object teacher = SmallAbstractBeanFactory.getBean("smallTeacher",SmallTeacher.class);
        System.out.println(teacher.toString());
    }
}

image.png

三、源码分析

3.流程全分析 - 初始化Student

由上面的 getBean,跳转到 AbstractBeanFactory 的 getBean 方法:

public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

3.1 doGetBean(student)

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // ......

            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // Explicitly remove instance from singleton cache: It might have been put there
                        // eagerly by the creation process, to allow for circular reference resolution.
                        // Also remove any beans that received a temporary reference to the bean.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            // ......
    return (T) bean;
}

在Lambda表达式中要调用 createBean ,但在调用之前先看一眼 getSingleton 方法:

3.2 【重要】getSingleton

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // ......
            // 标记当前bean
            beforeSingletonCreation(beanName);
            // .....
            try {
                // 创建Bean
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            // ......
}

beforeSingletonCreation 方法咱之前看过了:

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

它把当前的 student 放入 singletonsCurrentlyInCreation **(正在创建的Bean)**中。

接下来准备调用 singletonFactory.getObject() ,也就是调用下面的 createBean 方法:

3.3 createBean(student)

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

    // ......
    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    // ......
}

最终调到 doCreateBean 方法:

3.4 doCreateBean(student) & createBeanInstance

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // ......
    // 创建Bean实例
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // ......
    
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    
    // ......
    Object exposedObject = bean;
    try {
        // 属性赋值&自动注入
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    //......
    return exposedObject;
}

中间有一个非常关键的步骤:earlySingletonExposure 的判断。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // ......
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    // ......
}

3.5 earlySingletonExposure的判断 & addSingletonFactory

这个判断非常关键,它要同时成立三个条件才能进if结构:

  • 这个Bean是一个单实例Bean
  • IOC容器允许循环依赖(默认是true)
  • 正在创建的单实例Bean对象中有当前的这个Bean

由于在3.2环节中,singletonsCurrentlyInCreation 这个集合中已经把 student 放进去了,此时这个判断也为true

三个条件全为true,进入if结构中,它干了这么一件事:

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

来看 addSingletonFactory 的源码:

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

这一步的动作可以看出来,是将当前正在创建的Bean保存到三级缓存中,并从二级缓存中移除(由于本来二级缓存中没有,故可以只认定为放入三级缓存)。


下面的属性赋值&自动注入点:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // ......
    try {
        // 属性赋值&自动注入
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    //......
    return exposedObject;
}

3.6 populateBean(student)

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // ......
    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
    }
    //......
}

在这个 InstantiationAwareBeanPostProcessor 的for循环中,会调用 AutowiredAnnotationBeanPostProcessor 的 postProcessProperties 方法,触发自动注入。

3.7 AutowiredAnnotationBeanPostProcessor#postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    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 方法:

3.8 【注入】metadata.inject

跳转到 AutowiredFieldElement#inject 中:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    // ......
        try {
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
    // ......
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

一开始初始化的时候肯定找不到 Teacher ,要走 beanFactory.resolveDependency 方法:

3.9 beanFactory.resolveDependency

此时跳转到 DefaultListableBeanFactory 类中:

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    // if-else ......
    else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                descriptor, requestingBeanName);
        if (result == null) {
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

来到最后的 doResolveDependency 方法中:

3.10 doResolveDependency

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

    // try ......
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        // ......
}

Debug走到这一步,跳转进去的方法就是 getBean

4. 流程全分析 - 初始化Teacher

4.1 getBean(teacher)

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
        throws BeansException {
    return beanFactory.getBean(beanName);
}

继续往下走,回到 AbstractBeanFactory 了:

4.2 doGetBean(teacher) - getSingleton(teacher)

与上面的思路类似,不再贴源码,当执行到getSingleton方法时,要知道 beforeSingletonCreation 方法又执行了,此时正在创建的Bean有两个

4.3 createBean(teacher) - doCreateBean(teacher) -> addSingletonFactory

这几步操作最终完成的动作:将teacher放入三级缓存,并从二级缓存中移除

4.4 populateBean(teacher)

跟上面一样,也是同样的执行后置处理器,走inject方法。

4.5 metadata.inject - resolveDependency - doResolveDependency

最终也会像上面一样,执行到这一步:

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

    // try ......
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        // ......
}

进去会调getBean(student)。

4.6 再次getBean(student)

其实这里进的还是我们熟悉的那个getBean:

public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

下面还是那一套,不过进入 doGetBean 方法后有一个很重要的环节:getSingleton

4.7 【二次获取】getSingleton(student)

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

注意在这里第二次获取 student 的时候,由于现在 正在被创建的Bean 中有 student 了,所以 isSingletonCurrentlyInCreation(student) 将返回true!会进入到下面的if结构体中!

进入之后,它要确定 earlySingletonObjects 二级缓存 中是否有当前创建好但没有赋值初始化的Bean(当前student),此时根据前面的步骤,teacher和student均只在三级缓存,所以取出的 singletonObject 为null,进入第二层if的结构体中。再往下来,它又从 singletonFactories 三级缓存 中取当前正在创建的Bean(student),这次可以查到,于是进入第三层if的结构体。它干了两件事:将这个 student 放入二级缓存,并从三级缓存中移除。 那既然这里已经获取到了,那 singletonObject 自然有值,就可以正常返回那个 正在创建,但还没有注入依赖项的student 。

4.8 回到doGetBean(student)

    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        // log ......
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

获取到 student 后,下面会调用一个 getObjectForBeanInstance 方法:

4.9 getObjectForBeanInstance(student)

private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    String currentlyCreatedBean = this.currentlyCreatedBean.get();
    if (currentlyCreatedBean != null) {
        registerDependentBean(beanName, currentlyCreatedBean);
    }

    return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}

这里先通过 this.currentlyCreatedBean.get() 取到当前线程中正在创建的Bean的名称,发现为null(到目前为止也没发现谁在操作它,通过IDEA的提示,发现是 obtainFromSupplier 方法中有对它的操作,之前提过了我们不关心它),则直接调父类的 getObjectForBeanInstance 方法:

4.10 AbstractBeanFactory#getObjectForBeanInstance(student)

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    // 如果Bean不是工厂,则不要让调用代码尝试取消引用工厂
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    // ......
}

第一段if中,因为 student 不是被工厂引用的Bean,这部分不进入。

第二段if中,因为 student 不是一个工厂Bean,前半段返回true,直接返回student。

这段方法走完后,student还是那个student。

回到doGetBean方法:

4.11 再回到doGetBean(student)

    // Check if required type matches the type of the actual bean instance.
    // 检查所需的类型是否与实际bean实例的类型匹配
    if (requiredType != null && !requiredType.isInstance(bean)) {
        // ......
    }
    return (T) bean;

这一段if判断是确定bean与返回的类型是否一致,这里很明显一致,直接强转返回即可。

4.12 回到注入的部分(teacher)

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

    // ......
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

descriptor.resolveCandidate 方法执行完后,下面把bean交给result,确定没问题,返回出去。

4.13 回到resolveDependency(teacher)

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    // if-else ......
    else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                descriptor, requestingBeanName);
        if (result == null) {
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

这个方法也就成功返回student了。

4.14 返回inject方法(student)

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    // ......
        try {
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        // ......
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

取到value,也就是那个student的Bean后,最底下利用反射赋值,自动注入结束

4.15 回到doCreateBean(teacher)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // ......
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    //......
    return exposedObject;
}

teacher的属性赋值和自动注入完成后,执行初始化方法(没定义),最后返回出去。

4.16 回到createBean(teacher)

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    // ......
    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        // log ......
        return beanInstance;
    }
    // ......
}

也是直接返回出去。

4.17 回到DefaultSingletonBeanRegistry#getSingleton(teacher)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // ......
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            // catch ......
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

createBean 返回后回到Lambda表达式,又回到 getSingleton 方法中。创建的这个单实例Teacher会被 newSingleton 标记为true,在下面的finally块中,要执行两个重要的方法:afterSingletonCreation 和 addSingleton :

4.18 afterSingletonCreation

protected void afterSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
}

这部分的作用:将创建好的Bean从“正在创建中的Bean”中移除

4.19 【重要】addSingleton

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

这部分的作用:将创建的这个Bean放入一级缓存,从二级缓存和三级缓存中移除,并记录已经创建了的单实例Bean

至此,Teacher的创建完全结束。

5. 回到student的创建

5.1 回到DependencyDescriptor#resolveCandidate(student)

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
        throws BeansException {
    return beanFactory.getBean(beanName);
}

这个 getBean(teacher) 结束了,真正完全创建好的Teacher也返回来了。下面的步骤就与上面一样了,快速过一遍。

5.2 返回注入的部分(student)

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

    // ......
        if (instanceCandidate instanceof Class) {
            // teacher
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        // ......
        return result;
    }
    // ......
}

5.3 回到resolveDependency(student)

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    // if-else ......
    else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                descriptor, requestingBeanName);
        if (result == null) {
            // teacher
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

5.4 返回inject方法(student)

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    // ......
        try {
            // teacher
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        // ......
    }
    if (value != null) {
        //缓存teacher
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

5.5 回到doCreateBean(student)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // ......
    Object exposedObject = bean;
    try {
        // 自动注入完成
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    //......
    return exposedObject;
}

5.6 回到createBean(student)

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    // ......
    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        // log ......
        // 直接返回出去了
        return beanInstance;
    }
    // ......
}

5.7 回到DefaultSingletonBeanRegistry#getSingleton(student)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // ......
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            // catch ......
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                // 清除正在创建的缓存
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                // 创建完student后也要调这个方法
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

5.8 afterSingletonCreation

protected void afterSingletonCreation(String beanName) {
    // 清除正在创建的缓存
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
}

5.9 【重要】addSingleton

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        // 将student放入一级缓存
        this.singletonObjects.put(beanName, singletonObject);
        // 从二级缓存和三级缓存中移除
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        // 记录已经创建了的student
        this.registeredSingletons.add(beanName);
    }
}

至此,Student的创建完全结束。

四、为什么需要三级缓存?二级缓存不行吗?

这实际上涉及到 AOP,如果创建的 Bean是有代理的,那么注入的就应该是代理 Bean,而不是原始的 Bean。但是 Spring一开始并不知道 Bean是否会有循环依赖,通常情况下(没有循环依赖的情况下),Spring 都会在完成填充属性,并且执行完初始化方法之后再为其创建代理。但是,如果出现了循环依赖的话,Spring 就不得不为其提前创建代理对象,否则注入的就是一个原始对象,而不是代理对象。因此,这里就涉及到应该在哪里提前创建代理对象

如果要使用二级缓存解决循环依赖,意味着Bean在构造完后就创建代理对象,这样违背了Spring设计原则。

Spring结合AOP跟Bean的生命周期,是在Bean创建完全之后通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来完成的,在这个后置处理的postProcessAfterInitialization方法中对初始化后的Bean完成AOP代理。

如果出现了循环依赖,那没有办法,只有给Bean先创建代理,但是没有出现循环依赖的情况下,设计之初就是让Bean在生命周期的最后一步完成代理而不是在实例化后就立马完成代理。

使用三级缓存创建Bean的流程

image.png

不使用三级缓存只使用二级缓存创建Bean的流程 image.png