热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring5IOC容器解析——单例循环依赖的解决

什么是循环依赖循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环。A依赖B,B又依赖A,它们之间形成了循环依赖。或者是A依赖

什么是循环依赖

循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环。A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。或者是 A 依赖 B,B 依赖 C,C 又依赖 A。它们之间的依赖关系如下:

Spring5IOC容器解析——单例循环依赖的解决

注意,这里不是函数的循环调用,是对象的相互依赖关系。循环调用其实就是一个死循环,除非有终结条件。

Spring中循环依赖场景有:

  • 1、构造器的循环依赖
  • 2、field属性的循环依赖

其中,构造器的循环依赖问题是无法解决,只能拋出BeanCurrentlyInCreationException异常,在解决属性循环依赖时,spring采用的是提前暴露对象的方法。

怎么检测是否存在循环依赖

检测循环依赖相对比较容易,Bean在创建的时候可以给该Bean打标,如果递归调用回来发现正在创建中的话,即说明了循环依赖了。

三级缓存的介绍,用于解决单例Bean的循环依赖

/** Cache of singleton objects: bean name to bean instance. */
//一级缓存:单例对象缓存池,beanName->Bean,其中存储的就是实例化,属性赋值成功之后的单例对象
private final Map singletOnObjects= new ConcurrentHashMap(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
//三级缓存:单例工厂的缓存,beanName->ObjectFactory,添加进去的时候实例还未具备属性
// 用于保存beanName和创建bean的工厂之间的关系map,单例Bean在创建之初过早的暴露出去的Factory,
// 为什么采用工厂方式,是因为有些Bean是需要被代理的,总不能把代理前的暴露出去那就毫无意义了
private final Map> singletOnFactories= new HashMap(16);

/** Cache of early singleton objects: bean name to bean instance. */
//二级缓存:早期的单例对象,beanName->Bean,其中存储的是实例化之后,属性未赋值的单例对象
// 执行了工厂方法生产出来的Bean,bean被放进去之后,
// 那么当bean在创建过程中,就可以通过getBean方法获取到
private final Map earlySingletOnObjects= new HashMap(16);

根据缓存变量上面的注释,大家应该能大致了解他们的用途。我这里简单说明一下吧:

缓存 用途
singletonObjects 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用。
earlySingletonObjects 提前曝光的单例cache,存放原始的 bean 对象(尚未填
充属性),用于解决循环依赖。
singletonFactories 存放 bean 工厂对象,用于解决循环依赖。

Spring创建Bean的流程

Spring5IOC容器解析——单例循环依赖的解决
Spring IOC 容器中获取 bean 实例的流程
Spring5IOC容器解析——单例循环依赖的解决

对Bean的创建最为核心三个方法解释如下:

  • createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象
  • populateBean:填充属性,这一步主要是对bean的依赖属性进行注入(@Autowired)
  • initializeBean:回到一些形如initMethod、InitializingBean等方法

从对单例Bean的初始化可以看出,循环依赖主要发生在第二步(populateBean),也就是field属性注入的处理。

Spring怎么解决循环依赖,setter方式单例

Spring的循环依赖的理论依据基于Java的引用传递,当获得对象的引用时,对象的属性是可以延后设置的。(但是构造器必须是在获取引用之前)。

循环依赖解决方式: 三级缓存

由refresh()为入口切入, 这里只分析单例bean创建流程:

  • 1、AbstractBeanFactory.getBean为入口 并委托 AbstractBeanFactory.doGetBean创建。

  • 2、AbstractBeanFactory.doGetBean 会首先从AbstractBeanFactory.getSingleton中获取缓存的bean对象, 如果不存在则调用抽象方法createBean, 即子类实现的AbstractAutowireCapableBeanFactory.createBean方法。

  • 3、AbstractAutowireCapableBeanFactory.createBean方法触发doCreateBean依次调用以下方法实现bean创建过程:

    • A、createBeanInstance: 实例化bean, 如果需要依赖其他对象则首先创建其他对象(发生循环依赖的地方)
    • B、addSingletonFactory: 将实例化bean加入三级缓存
    • C、populateBean: 初始化bean, 如果需要依赖其他对象则首先创建其他对象(发生循环依赖的地方)
    • D、initializeBean
    • E、registerDisposableBeanIfNecessary

如果是构造函数注入的话在createBeanInstance方法中会调用autowireConstructor

  • 1、AbstractAutowireCapableBeanFactory.autowireConstructor使用构造函数进行实例化。

  • 2、最终调用 ConstructorResolver.autowireConstructor 和 ConstructorResolver.resolveConstructorArguments 进行实例化已经解析构造参数。

  • 3、调用BeanDefinitionValueResolver.resolveValueIfNecessary 和 BeanDefinitionValueResolver.resolveReference 模版类解析构造参数。

步骤配上代码:

1、AbstractBeanFactory.getBean为入口 并委托 AbstractBeanFactory.doGetBean创建。

@Override
public Object getBean(String name) throws BeansException {
    // 获取name对应的bean实例,如果不存在,则创建一个
    return doGetBean(name, null, null, false);
}

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

    // 1.解析beanName,主要是解析别名、去掉FactoryBean的前缀“&”
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // 2.尝试从缓存中获取beanName对应的实例
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        // 3.如果beanName的实例存在于缓存中
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 3.1 返回beanName对应的实例对象(主要用于FactoryBean的特殊处理,普通Bean会直接返回sharedInstance本身)
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 4.scope为prototype的循环依赖校验:如果beanName已经正在创建Bean实例中,而此时我们又要再一次创建beanName的实例,则代表出现了循环依赖,需要抛出异常。
        // 例子:如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        // 5.获取parentBeanFactory
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 5.1 如果parentBeanFactory存在,并且beanName在当前BeanFactory不存在Bean定义,则尝试从parentBeanFactory中获取bean实例
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            // 5.2 将别名解析成真正的beanName
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            // 5.3 尝试在parentBeanFactory中获取bean对象实例
            else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        if (!typeCheckOnly) {
            // 6.如果不是仅仅做类型检测,而是创建bean实例,这里要将beanName放到alreadyCreated缓存
            markBeanAsCreated(beanName);
        }

        try {
            // 7.根据beanName重新获取MergedBeanDefinition(步骤6将MergedBeanDefinition删除了,这边获取一个新的)
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 7.1 检查MergedBeanDefinition
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            // 8.拿到当前bean依赖的bean名称集合,在实例化自己之前,需要先实例化自己依赖的bean
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                // 8.1 遍历当前bean依赖的bean名称集合
                for (String dep : dependsOn) {
                    // 8.2 检查dep是否依赖于beanName,即检查是否存在循环依赖
                    if (isDependent(beanName, dep)) {
                        // 8.3 如果是循环依赖则抛异常
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 8.4 将dep和beanName的依赖关系注册到缓存中
                    registerDependentBean(dep, beanName);
                    try {
                        // 8.5 获取dep对应的bean实例,如果dep还没有创建bean实例,则创建dep的bean实例
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            // 9.针对不同的scope进行bean的创建
            if (mbd.isSingleton()) {
                // 9.1 scope为singleton的bean创建(新建了一个ObjectFactory,并且重写了getObject方法)
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 9.1.1 创建Bean实例
                        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;
                    }
                });
                // 9.1.2 返回beanName对应的实例对象
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                // 9.2 scope为prototype的bean创建
                Object prototypeInstance = null;
                try {
                    // 9.2.1 创建实例前的操作(将beanName保存到prototypesCurrentlyInCreation缓存中)
                    beforePrototypeCreation(beanName);
                    // 9.2.2 创建Bean实例
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    // 9.2.3 创建实例后的操作(将创建完的beanName从prototypesCurrentlyInCreation缓存中移除)
                    afterPrototypeCreation(beanName);
                }
                // 9.2.4 返回beanName对应的实例对象
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                // 9.3 其他scope的bean创建,可能是request之类的
                // 9.3.1 根据scopeName,从缓存拿到scope实例
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    // 9.3.2 其他scope的bean创建(新建了一个ObjectFactory,并且重写了getObject方法)
                    Object scopedInstance = scope.get(beanName, () -> {
                        // 9.3.3 创建实例前的操作(将beanName保存到prototypesCurrentlyInCreation缓存中)
                        beforePrototypeCreation(beanName);
                        try {
                            // 9.3.4 创建bean实例
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            // 9.3.5 创建实例后的操作(将创建完的beanName从prototypesCurrentlyInCreation缓存中移除)
                            afterPrototypeCreation(beanName);
                        }
                    });
                    // 9.3.6 返回beanName对应的实例对象
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            // 如果创建bean实例过程中出现异常,则将beanName从alreadyCreated缓存中移除
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    // 10.检查所需类型是否与实际的bean对象的类型匹配
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            // 10.1 类型不对,则尝试转换bean类型
            T cOnvertedBean= getTypeConverter().convertIfNecessary(bean, requiredType);
            if (cOnvertedBean== null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    // 11.返回创建出来的bean实例对象
    return (T) bean;
}

2、AbstractBeanFactory.doGetBean 会首先从AbstractBeanFactory.getSingleton中获取缓存的bean对象, 如果不存在则调用抽象方法createBean, 即子类实现的AbstractAutowireCapableBeanFactory.createBean方法。

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    /** Cache of singleton objects: bean name to bean instance. */
    //一级缓存:单例对象缓存池,beanName->Bean,其中存储的就是实例化,属性赋值成功之后的单例对象
    private final Map singletOnObjects= new ConcurrentHashMap(256);

    /** Cache of singleton factories: bean name to ObjectFactory. */
    //三级缓存:单例工厂的缓存,beanName->ObjectFactory,添加进去的时候实例还未具备属性
    // 用于保存beanName和创建bean的工厂之间的关系map,单例Bean在创建之初过早的暴露出去的Factory,
    // 为什么采用工厂方式,是因为有些Bean是需要被代理的,总不能把代理前的暴露出去那就毫无意义了
    private final Map> singletOnFactories= new HashMap(16);

    /** Cache of early singleton objects: bean name to bean instance. */
    //二级缓存:早期的单例对象,beanName->Bean,其中存储的是实例化之后,属性未赋值的单例对象
    // 执行了工厂方法生产出来的Bean,bean被放进去之后,
    // 那么当bean在创建过程中,就可以通过getBean方法获取到
    private final Map earlySingletOnObjects= new HashMap(16);

    /** Names of beans that are currently in creation. */
    //三级缓存是用来解决循环依赖,而这个缓存就是用来检测是否存在循环依赖的
    private final Set singletOnsCurrentlyInCreation=
            Collections.newSetFromMap(new ConcurrentHashMap(16));

    /** Names of beans currently excluded from in creation checks. */
    //直接缓存当前不能加载的bean
    private final Set inCreatiOnCheckExclusions=
            Collections.newSetFromMap(new ConcurrentHashMap(16));

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 1.从单例对象缓存中获取beanName对应的单例对象
        Object singletOnObject= this.singletonObjects.get(beanName);
        // 2.如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
        if (singletOnObject== null && isSingletonCurrentlyInCreation(beanName)) {
            //尝试给一级缓存对象加锁,因为接下来就要对缓存对象操作了
            synchronized (this.singletonObjects) {
                // 4.从早期单例对象缓存中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里
                // 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
                //尝试从二级缓存earlySingletonObjects这个存储还没进行属性添加操作的Bean实例缓存中获取
                singletOnObject= this.earlySingletonObjects.get(beanName);
                // 5.如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
                //如果还没有获取到并且第二个参数为true,为true则表示bean允许被循环引用
                if (singletOnObject== null && allowEarlyReference) {
                    // 6.从单例工厂缓存中获取beanName的单例工厂
                    //从三级缓存singletonFactories这个ObjectFactory实例的缓存里尝试获取创建此Bean的单例工厂实例
                    ObjectFactory> singletOnFactory= this.singletonFactories.get(beanName);
                    //如果获取到工厂实例
                    if (singletonFactory != null) {
                        // 7.如果存在单例对象工厂,则通过工厂创建一个单例对象
                        singletOnObject= singletonFactory.getObject();
                        // 8.将通过单例对象工厂创建的单例对象,放到早期单例对象缓存中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 9.移除该beanName对应的单例对象工厂,因为该单例工厂已经创建了一个实例对象,并且放到earlySingletonObjects缓存了,
                        // 因此,后续获取beanName的单例对象,可以通过earlySingletonObjects缓存拿到,不需要在用到该单例工厂
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        // 10.返回单例对象
        return singletonObject;
    }
}
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

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

        if (logger.isTraceEnabled()) {
            logger.trace("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.
        //判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载。
        Class> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            // 如果resolvedClass存在,并且mdb的beanClass类型不是Class,并且mdb的beanClass不为空(则代表beanClass存的是Class的name),
            // 则使用mdb深拷贝一个新的RootBeanDefinition副本,并且将解析的Class赋值给拷贝的RootBeanDefinition副本的beanClass属性,
            // 该拷贝副本取代mdb用于后续的操作
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
            // 2.验证及准备覆盖的方法(对override属性进行标记及验证)
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            // 3.实例化前的处理,给InstantiationAwareBeanPostProcessor一个机会返回代理对象来替代真正的bean实例,达到“短路”效果
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            // 4.如果bean不为空,则会跳过Spring默认的实例化过程,直接使用返回的bean
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            // 5.创建Bean实例(真正创建Bean的方法)
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            // 6.返回创建的Bean实例
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }
}

3、AbstractAutowireCapableBeanFactory.createBean方法触发doCreateBean依次调用以下方法实现bean创建过程:

  • A、createBeanInstance: 实例化bean, 如果需要依赖其他对象则首先创建其他对象(发生循环依赖的地方)
  • B、addSingletonFactory: 将实例化bean加入三级缓存
  • C、populateBean: 初始化bean, 如果需要依赖其他对象则首先创建其他对象(发生循环依赖的地方)
  • D、initializeBean
  • E、registerDisposableBeanIfNecessary
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        // 1.新建Bean包装类
        BeanWrapper instanceWrapper = null;
        //如果RootBeanDefinition是单例的,则移除未完成的FactoryBean实例的缓存
        if (mbd.isSingleton()) {
            // 2.如果是FactoryBean,则需要先移除未完成的FactoryBean实例的缓存
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 3.根据beanName、mbd、args,使用对应的策略创建Bean实例,并返回包装类BeanWrapper
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 4.拿到创建好的Bean实例
        final Object bean = instanceWrapper.getWrappedInstance();
        // 5.拿到Bean实例的类型
        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 {
                    // 6.应用后置处理器MergedBeanDefinitionPostProcessor,允许修改MergedBeanDefinition,
                    // Autowired注解、Value注解正是通过此方法实现注入类型的预解析
                    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.
        // 7.判断是否需要提早曝光实例:单例 && 允许循环依赖 && 当前bean正在创建中
        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");
            }
            // 8.提前曝光beanName的ObjectFactory,用于解决循环引用
            // 8.1 应用后置处理器SmartInstantiationAwareBeanPostProcessor,允许返回指定bean的早期引用,若没有则直接返回bean
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        // 初始化bean实例。
        Object exposedObject = bean;
        try {
            // 9.对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例
            populateBean(beanName, mbd, instanceWrapper);
            // 10.对bean进行初始化
            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) {
            // 11.如果允许提前曝光实例,则进行循环依赖检查
            Object earlySingletOnReference= getSingleton(beanName, false);
            // 11.1 earlySingletonReference只有在当前解析的bean存在循环依赖的情况下才会不为空
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    // 11.2 如果exposedObject没有在initializeBean方法中被增强,则不影响之前的循环引用
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    // 11.3 如果exposedObject在initializeBean方法中被增强 && 不允许在循环引用的情况下使用注入原始bean实例
                    // && 当前bean有被其他bean依赖
                    // 11.4 拿到依赖当前bean的所有bean的beanName数组
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        // 11.5 尝试移除这些bean的实例,因为这些bean依赖的bean已经被增强了,他们依赖的bean相当于脏数据
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            // 11.6 移除失败的添加到 actualDependentBeans
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        // 11.7 如果存在移除失败的,则抛出异常,因为存在bean依赖了“脏数据”
                        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 {
            // 12.注册用于销毁的bean,执行销毁操作的有三种:自定义destroy方法、DisposableBean接口、DestructionAwareBeanPostProcessor
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }
        // 13.完成创建并返回
        return exposedObject;
    }
}

主要的步骤为:

  • 1、Bean A的首次创建,会调用doCreateBean方法,在doCreateBean方法里会经过层层包装,在调用createBeanInstance方法之后,会创建一个没有任何属性的Bean的实例,并返回该实例的包装类BeanWrapper。

  • 2、在调用addSingletonFactory方法之前,将Bean A实例放入ObjectFactory里面,然后调用addSingletonFactory方法将Bean A相关的ObjectFactory实例添加到三级缓存singletonFactories中,此时只有三级缓存中保存了该Bean 对应的ObjectFactory实例。

  • 3、随后调用populateBean方法给属性赋值,由于Bean A直接依赖于Bean B,所以在populateBean方法中会再次调用getBean方法在容器里去尝试获取Bean B的实例。此时由于Bean B实例还没有创建出来,因此又会递归的调用到doCreateBean方法,在doCreateBean方法中调用createBeanInstance方法创建出Bean B实例,并将其对应的ObjectFactory方法放入到三级缓存中,此时三级缓存中就保存了循环依赖的Bean A和B的各自的ObjectFactory实例。

  • 4、随后在Bean B实例又会调用populateBean方法给其属性赋值。此时由于Bean B又依赖于Bean A,所以在populateBean方法中又会调用getBean方法尝试获取Bean A实例。

  • 5、此时会调用AbstractBeanFactory中的doGetBean方法,doGetBean方法会尝试调用getSingleton方法从三级缓存中去获取Bean A的实例。而在一级缓存singletonObjects和二级缓存earlySingletonObjects中都获取不到,而在三级缓存singletonFactories中获取到Bean A实例对应的ObjectFactory实例,调用其getObject方法获取Bean A实例。通过getObject方法获取到了Bean A实例之后,将A实例放入到二级缓存中,同时清空三级缓存中的实例,并将Bean A实例返回。

  • 6、由于Bean A实例实在Bean B实例执行populateBean方法的时候获取到了,此时已经将Bean A实例注入到了Bean B实例中,此时Bean B会执行完doCreateBean的剩余方法,并返回一个初始化完整的Bean实例。

  • 7、由于doCreateBean方法是通过doGetBean方法调用的,所以会将完整的Bean B实例逐层返回到doGetBean方法(AbstractBeanFactory)中。而AbstractBeanFactory的getSingleton方法在执行singletOnObject= singletonFactory.getObject()代码时,才正式执行createBean方法。

  • 8、在getSingleton方法中会最终执行addSingleton(beanName, singletonObject)方法,在addSingleton方法中会将Bean B实例添加进一级缓存singletonObjects中,并将Bean B实例从二级缓存(earlySingletonObjects)和三级缓存(singletonFactories)中清除,此时表明彻底完成了Bean B实例的创建,随后将完整的Bean B实例返回。

  • 9、Bean B实例的创建是由于Bean A实例调用populateBean方法触发的,所以此时,又会回到创建Bean A时的populateBean方法中,此时Bean A就赋值上了完整的Bean B,在Bean A实例完整创建之后又会逐层返回到doGetBean方法中,之后又会调用addSingleton将Bean A实例放入到一级缓存中,同时清除二级和三级缓存中的Bean A实例。

Spring5IOC容器解析——单例循环依赖的解决
Spring解决循环依赖

循环依赖的情况

  • 构造函数循环依赖(singleton、prototype)
  • Setter注入循环依赖(singleton、prototype)

对于prototype的Bean,Spring默认是不支持相关的循环依赖

// 4.scope为prototype的循环依赖校验:如果beanName已经正在创建Bean实例中,而此时我们又要再一次创建beanName的实例,则代表出现了循环依赖,需要抛出异常。
// 例子:如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
}

单例Setter注入循环依赖(singleton)问题的解决,主要是单例的三级缓存,三级缓存除了解决循环依赖之外,还解决了保持单例唯一性的问题,因为从缓存中取出来的Bean实例是要保证唯一的,所以三级缓存支持不了prototype,因为prototype的Bean实例不唯一。

正式因为没有三级缓存的支持,才导致prototype不支持循环依赖。

构造函数循环依赖(singleton)【这个Spring解决不了】

由于单例的构造函数注入方式,实在doCreateBean方法中的createBeanInstance方法中完成的,此时还没有三级缓存。在createBeanInstance方法中的autowireConstructor(beanName, mbd, ctors, args)方法中进行Bean的实例化和参数注入,而此时构造函数的实例参数并没有构造出来,所以构造函数的参数实例也会调用getBean方法去创建实例参数,而实例参数又需要之前依赖的实例参数,最后又会递归到autowireConstructor方法,所以导致无限循环。

参考:
https://blog.nowcoder.net/n/2bb528b258b44c7eab1703a52170ef09

https://blog.csdn.net/weixin_30951389/article/details/97471000

https://www.cnblogs.com/liuqing576598117/p/11227007.html


推荐阅读
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 更新vuex的数据为什么用mutation?
    更新vuex的数据为什么用mutation?,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文介绍了如何在 Spring 3.0.5 中使用 JdbcTemplate 插入数据并获取 MySQL 表中的自增主键。 ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • JVM钩子函数的应用场景详解
    本文详细介绍了JVM钩子函数的多种应用场景,包括正常关闭、异常关闭和强制关闭。通过具体示例和代码演示,帮助读者更好地理解和应用这一机制。适合对Java编程和JVM有一定基础的开发者阅读。 ... [详细]
  • 本文详细介绍了如何在Unity中实现一个简单的广告牌着色器,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • com.hazelcast.config.MapConfig.isStatisticsEnabled()方法的使用及代码示例 ... [详细]
author-avatar
手机用户2502891655
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有