Spring源码-存在AOP的循环依赖(Spring Framework 5.3.7-SNAPSHOT)

三级缓存
  • singletonObjects,也叫一级缓存,存放已完成初始化后的对象
  • earlySingletonObjects,二级缓存,存放已完成实例化,但未完成初始化的对象
  • singletonFactories,三级缓存,存放刚刚完成实例化,但未开始初始化的单例对象
AOP的循环依赖的正常示例
// DataHandler和MathCalculator分别会被切面织入
@Component
public class DataHandler {

    @Autowired
    private MathCalculator calculator;

    public DataHandler() {
        System.out.println("DataHandler的默认构造函数");
    }

    public Object processData(Object dataParam) {
        System.out.println("调用DataHandler的processData方法");
        return new Object();
    }

}

@Component
public class MathCalculator {

    @Autowired
    private DataHandler dataHandler;

    public MathCalculator() {
        System.out.println("MathCalculator的默认构造函数");
    }

    @Override
    public double div(int i, int j) {
        System.out.println("\t执行业务逻辑方法MathCalculator#div");
        return i / j;
    }
}
  • 结合三级缓存,如何解决?
  • 首先实例化dataHandler之后,会被放入三级缓存singletonFactories
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // factoryBeanInstanceCache存储的是:beanName对应的FactoryBean实例对象
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 根据构造函数实例化,创建Bean实例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 返回的是原始对象,创建的Bean中属性值为null
    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 {
                // 扩展点 TODO
                // 此步骤功能点包括:AutowiredAnnotationBeanPostProcessor对@Autowired预解析
                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.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        // 此时bean没有完成属性注入,构造一个ObjectFactory放入第三级缓存singletonFactories中,
        // 便于下面的getSingleton方法,从singletonFactories中取出并执行lambda表达式
        // 第三级缓存,为了应对当前Bean在后面出现循环依赖的情况,就可以通过lambda表达式进行AOP的逻辑
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    // 对象已经暴露出去
    Object exposedObject = bean;
    try {
        // 填充属性@Autowired
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化Bean、应用BeanPostProcessor
        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);
        }
    }

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

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}
  • 执行addSingletonFactory方法,把dataHandler对应的lambda表达式存入三级缓存,接下来进行属性赋值populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 省略
    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);

    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // 构造函数注入,set方法注入,@Value注入的逻辑在此处完成
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}
  • 着重关注AutowiredAnnotationBeanPostProcessor的postProcessProperties方法,这里会解析DataHandler依赖的MathCalculator对象
@Override
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;
}
  • 解析MathCalculator实际注入的值
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    if (this.cached) {
        try {
            value = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Unexpected removal of target bean for cached argument -> re-resolve
            value = resolveFieldValue(field, bean, beanName);
        }
    }
    else {
        // 解析依赖的mathCalculator
        value = resolveFieldValue(field, bean, beanName);
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}
  • resolveFieldValue的主要逻辑如下:
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
    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();
    Object value;
    try {
        // 最终会调用DefaultListableBeanFactory的doResolveDependency
        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    }
    catch (BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    }
    // 省略
    return value;
}
  • doResolveDependency
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }

        Class<?> type = descriptor.getDependencyType();
        // 解析@Value注解
        // 省略
        // 考虑属性的不同情况:数组类型、Collection类型、Map类型
        // 省略

        // 解析@Autowired依赖的多个bean,找到真正的候选bean
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        if (matchingBeans.size() > 1) {
            // 如果有多个bean,如:同一个接口存在多个实现类,根据@Primary决定候选的bean
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                }
                else {
                    // In case of an optional Collection/Map, silently ignore a non-unique case:
                    // possibly it was meant to be an empty collection of multiple regular beans
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        } else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        // 对于还没有在Spring Ioc容器中创建的依赖项,如:mathCalculator属性还没有经过完整的生命周期,通过此步骤往单例缓存池中存入对应的bean
        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);
    }
}
  • resolveCandidate实际是开始deGetBean的逻辑,此时beanName是mathCalculator,过程与获取dataHandler对应的Bean一样,在调用属性赋值populateBean函数之前,把mathCalculator存入三级缓存
  • 继续调用,直到又调用到resolveCandidate,此时beanName是dataHandler,接下来会从三级缓存中取出之前存入的lambda并执行,执行的结果是DataHandler的代理对象,存入二级缓存,并删除三级缓存
  • 一直回退到inject方法,此步骤完成MathCalculator的DatHandler属性填充(填充的是代理对象)
@Override
    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Field field = (Field) this.member;
        Object value;
        if (this.cached) {
            // 省略
        }
        else {
            // 此时返回的是DataHandler的代理对象
            value = resolveFieldValue(field, bean, beanName);
        }
        if (value != null) {
            ReflectionUtils.makeAccessible(field);
            // 把MathCalculaotr依赖的DataHandler属性值,填充进去
            field.set(bean, value);
        }
    }
  • 紧接着完成MathCalculator的initializeBean方法,此时生成了MathCalculator对象(代理对象),最终会存入一级缓存,并删除三级缓存(这里可以作个对比:DataHandler是先从三级缓存移到二级缓存,再从二级缓存移入一级缓存,而MathCalculator是直接从三级缓存移入一级缓存),程序继续执行
  • 接下来在inject方法中完成DataHandler的属性填充,接着执行initializeBean,此时得到的DataHandler并不是代理对象
  • 然后因为earlySingletonExposure为true,会调用getSingleton("dataHandler",false),这里直接从二级缓存中获取,因为之前已存放过,就是代理对象。取出来返回,最终存入一级缓存,并删除二级、三级缓存
@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    // 创建A的过程中,依赖B,然后去创建B,发现B又依赖A,则接下来的流程就是找依赖的A的流程
    // 先从一级缓存中取
    Object singletonObject = this.singletonObjects.get(beanName);

    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 如果一级缓存中为空,且正在创建中,则从二级缓存中取
        singletonObject = this.earlySingletonObjects.get(beanName);
        // 如果从二级缓存中取为空,且允许循环依赖
        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) {
                            // 执行lambda表达式:AOP
                            singletonObject = singletonFactory.getObject();
                            // 把执行AOP逻辑后的结果放入第二级缓存
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            // lambda只能执行一次,所以需要从第三级缓存中移除
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}
  • 到此步骤,对于AOP的循环依赖就完成,可以看出,解决循环依赖,3个缓存的设计非常精髓!尤其是singletonFactories很关键!
AOP的循环依赖的异常示例
  • 如果DataHandler,MathCalculator其中之一实现了接口,循环依赖过程中程序会抛BeanNotOfRequiredTypeException异常,如:"Bean named dataHandler is expected to be of type DataHandler but was actually of type $ProxyXXX,可以设置proxyTargetClass=true,不报错!
  • 原因在于,在doResolveDependency解析依赖的时候,有个判断,具体见源码:
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    // 省略
    try {
        // 省略
        // 对于还没有在Spring Ioc容器中创建的依赖项,如:属性还没有经过完整的生命周期,通过此步骤往单例缓存池中存入对应的bean
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        // 省略
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    // 省略
}
  • 和正常的示例的区别就是:对于实现了接口的类,通过JDK动态代理解析出的代理对象通过if条件判断为true,导致抛出实际解析出的类型和预期的类型不一致的异常
总结
  • 对于存在AOP的循环依赖,如果依赖项其中之一实现了接口,则会抛异常,实际编码过程中需要注意!可以在注解@EnableAspectJAutoProxy设置proxyTargetClass=true,使用CGLIB代理,避免报错。
  • 如果存在循环依赖且依赖项都实现了接口,但是不存在AOP,程序正常运行!
上一篇:Netty源码分析系列之一:NIO 基础介绍


下一篇:你需要知道的三个CSS技巧