Spring源码分析(十五)循环依赖2:源码分析

源码分析1:三级缓存

假设单例A、单例B之间循环依赖

假设先创建A

org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

在这里插入图片描述

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

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {...}
            if (logger.isDebugEnabled()) {...}
            //1.标记A正在创建中
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {...}
            try {
                //实际会调用createBean方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {...}
            catch (BeanCreationException ex) {...}
            finally {...}
            if (newSingleton) {...}
        }
        return singletonObject;
    }
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
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()) {...}
    
    //实例化阶段
    if (instanceWrapper == null) {...}
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {...}

    // Allow post-processors to modify the merged bean definition.
    //BeanDefintion后置处理阶段
    synchronized (mbd.postProcessingLock) {...}

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 急切地缓存单例,以便能够解析循环引用,即使是由BeanFactoryAware等生命周期接口触发的。

    // 是单例、且允许循环依赖(allowCircularReferences默认是true)、
    // 且当前Bean正在创建中(getSingleton的时候已经标记创建中了)
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {...}
        //2. 添加三级缓存
        // 往三级缓存中添加ObjectFactory
        // 此时还不知道会不会出现循环依赖,后面也许会用到,也许用不到。
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        //属性填充阶段(假设A要注入B,注入的过程中最终会再次调getBean拿B)
        populateBean(beanName, mbd, instanceWrapper);
        //初始化阶段
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {...}

    if (earlySingletonExposure) {...}

    // Register bean as disposable.
    try {...}
    catch (BeanDefinitionValidationException ex) {...}

    return exposedObject;
}

在这里插入图片描述

可以让容器关闭循环依赖:


在这里插入图片描述

1.标记A正在创建中

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

protected void beforeSingletonCreation(String beanName) {
    //inCreationCheckExclusions:当前从创建检查中排除的bean的名称。
    //singletonsCurrentlyInCreation:往这个集合中添加元素,如果已经存在返回false,说明已经在创建中了
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

2. 添加三级缓存

是单例、且允许循环依赖(allowCircularReferences默认是true)、且当前Bean正在创建中,则添加三级缓存。
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#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)) {
            //singletonFactories三级缓存
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

A属性填充阶段注入B

创建A的过程中,到了属性填充阶段,就会开始注入B了,此时会再次调getBean找B

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

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

    String beanName = transformedBeanName(name);
    Object beanInstance;

    // Eagerly check singleton cache for manually registered singletons.
    // 1. 先从单例池中找B,肯定找不到B,且B还没有开始创建
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {...}
    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        if (isPrototypeCurrentlyInCreation(beanName)) {...}

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {...}

        if (!typeCheckOnly) {...}

        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
                .tag("beanName", name);
        try {
            if (requiredType != null) {...}
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {...}

            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        //2. 创建单例B
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {...}
                });
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            else if (mbd.isPrototype()) {...}
            else {...}
        }
        catch (BeansException ex) {...}
        finally {...}
    }
    return adaptBeanInstance(name, beanInstance, requiredType);
}

1. 先从单例池中找B

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

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

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    // 此时单例池中是找不到B的,并且B还没有在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {...}
    return singletonObject;
}

检查是否正在创建中:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#isSingletonCurrentlyInCreation

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

此时单例池中是找不到B的,并且B还没有在创建中,所以会开始创建B。
同理B也会先标记B正在创建中,然后添加三级缓存,到了B属性填充阶段,会去注入A

B属性填充阶段注入A

创建B的过程中,到了属性填充阶段开始注入A,此时会再次调getBean找A

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

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

    String beanName = transformedBeanName(name);
    Object beanInstance;

    // Eagerly check singleton cache for manually registered singletons.
    // 急切地检查手动注册的单例缓存。

    // 1.从三级缓存中找A
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {...}
    else {...}

    return adaptBeanInstance(name, beanInstance, requiredType);
}

1. 从三级缓存中找A

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

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

//allowEarlyReference:是否允许创建早期引用
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    // 此时单例池中是找不到A的,但是发现A已经在创建中了
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        //去二级缓存拿,此时也拿不到的
        singletonObject = this.earlySingletonObjects.get(beanName);
        //拿不到判断是否允许创建早期引用,此时allowEarlyReference=true
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                // Consistent creation of early reference within full singleton lock
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                        //允许创建早期引用,则拿三级缓存创建
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            //执行三级缓存的getObject拿到最终需要注入的对象
                            //此时如果是AOP则返回代理对象,不是AOP返回普通对象
                            singletonObject = singletonFactory.getObject();
                            //将三级缓存生成的对象(最终注入的对象)放到二级缓存
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            //用不到了,就移除了
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    //此时返回"半成品"对象
    return singletonObject;
}

解决循环依赖,其实核心代码就两段逻辑,一个是放入三级缓存,一个从三个缓存中取值

源码分析2:AOP情况针对循环依赖的处理

保证不会重复AOP生成代理对象

如果发生循环依赖,且是AOP情况,会提前生成代理对象
在这里插入图片描述
而正常流程是在初始化后生成代理对象的
所以初始化后这里肯定要做一个控制,如果已经提前进行过AOP就不能再进行AOP了

看下提前进行AOP执行的代码:

在这里插入图片描述

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

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
            //提前AOP,代表发生循环依赖,且会调getEarlyBeanReference
            //正常AOP,无论是否发生循环依赖,都会调postProcessAfterInitialization
            exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
        }
    }
    return exposedObject;
}

只关心AOP的实现:
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference

//发生循环依赖才会调用这个方法,提前获取bean引用
public Object getEarlyBeanReference(Object bean, String beanName) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    //记录一下当前Bean发生了循环依赖,并提前获取Bean引用了
    
    //即记录当前Bean进行了AOP,注意此时bean是原始对象
    this.earlyProxyReferences.put(cacheKey, bean);
    //AOP,返回代理对象
    return wrapIfNecessary(bean, beanName, cacheKey);
}

//同时对比一下初始化后执行的方法,无论是否发生循环依赖都会执行
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            //earlyProxyReferences里取的是null != bean,说明之前没进行过AOP,才会进行AOP
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    //当前正在创建的Bean不用进行AOP,比如切面Bean
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    // 判断当前Bean是否存在匹配的advice,如果存在则要生成一个代理对象
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        //advisedBeans记录了某个Bean已经进行过AOP了
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        //要AOP,返回代理对象
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    //不要AOP,返回普通对象
    return bean;
}

保证最终单例池里放入正确的对象

A在初始化后发现已经提前AOP了,就不会再进行AOP了,之后要把A放到单例池里去
思考一下,此时放到单例池里的是原始对象还是代理对象?

再看一下初始化后的方法:

在这里插入图片描述

AOP的实现:

在这里插入图片描述

即初始化后方法得到的对象,有两种情况:

  • 如果提前AOP了(发生循环依赖了),初始化后方法得到的就是原始对象
  • 如果没有提前AOP(没有发生循环依赖),初始化后方法得到的就是代理对象

如果发生循环依赖,提前AOP生成代理对象,虽然在初始化后阶段不会重复生成代理对象,但返回出去的是原始对象,而最终放入单例池的肯定希望是AOP的代理对象,那从哪里获得?二级缓存。

看下初始化后之后做了什么:
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()) {... }
    //实例化阶段
    if (instanceWrapper == null) {...}
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {...}
    
	//BeanDefinition后置处理
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {...}

    // 循环依赖 - 设置三级缓存
    // 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) {...}

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        //属性填充阶段
        populateBean(beanName, mbd, instanceWrapper);
        
        //初始化阶段(初始化前、初始化、初始化后)
        //注意,如果没有发生循环依赖,这里得到的就是代理对象
        //如果发生了循环依赖,这里得到的就是原始对象(大部分情况)
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {...}

    //关键这里!!
    if (earlySingletonExposure) {//如果支持循环依赖
        //再次getBean,此时会从二级缓存拿到对象!!此时二级缓存存的就是“最终的"对象引用
    	//本质是执行多次SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference得到的对象
        Object earlySingletonReference = getSingleton(beanName, false);
        //能拿到,说明发生了循环依赖!!!
        if (earlySingletonReference != null) {
            //发生循环依赖以后
            //exposedObject:初始化后得到的对象
            //bean:一开始实例化的原始对象
            //比较  初始化后拿到的对象  和 一开始实例化的原始对象
            if (exposedObject == bean) {//大部分情况肯定一样的,先考虑简单场景
                //一样的话拿二级缓存的,替换exposedObject,最终返回
                //所以哪怕发生循环依赖,也能正常返回最终的那个代理对象
                exposedObject = earlySingletonReference;
            }
            //下面这段逻辑是处理:初始化后替换的对象 与 提前获取引用生成的对象 不一样冲突的情况
            //比较复杂,感兴趣就看https://www.yuque.com/qhao/framework/dxfpaw#FjcPV
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {...}
    }

    // Register bean as disposable.
    try {...}
    catch (BeanDefinitionValidationException ex) {...}
    return exposedObject;
}

所以哪怕发生循环依赖,也能通过二级缓存,正常返回最终的那个代理对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

犬豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值