当前位置:   article > 正文

spring 循环依赖

spring 循环依赖

单例bean循环依赖:

先创建ABean

1.0. 记录正在创建ABean singletonCurrentlyInCreation<ABean>
1.1.实例化ABean–>得到一个对象–>存入singletonFactories
1.2. 填充BBean属性–>去单例池找BBean–>没有就创建
1.3. 进行其他依赖注入
1.4. 初始化前,初始化
1.5. 初始化后
1.6. 放入单例池

创建BBean
2.1. 实例化BBean–>得到一个对象
2.2. 填充ABean属性–>去单例池找ABean–>没有就判断creatingSet–>出现循环依赖–>earlySingletonObjects–>singletonFactories–>Lambda表达式–>执行–> 执行结果创建ABean代理对象或者ABean原始对象,存入earlySingletonObject
2.3. 进行其他依赖注入
2.4. 初始化前,初始化
2.5. 初始化后
2.6. 放入单例池

创建CBean
3.1. 实例化BBean–>得到一个对象
3.2. 填充ABean属性–>去单例池找ABean–>没有就判断creatingSet–>出现循环依赖–>从earlySingletonObjec获取ABean
3.3. 进行其他依赖注入
3.4. 初始化前,初始化
3.5. 初始化后
3.6. 放入单例池

在ABean执行到1.2时会去创建BBean,进入到BBean的生命周期,造成循环依赖

spring为了解决循环依赖进行了三级缓存

1.singletonObjects 单例池
2.earlySingletonObjects 没有经过完整生命周期的单例对象,主要作用时保存单例bean对象,而跳出循环依赖
3.singletonFactories 实例化后没有经过依赖注入的对象,主要作用时生成单例bena对象,并将其存入earlySingletonObjects

//this.getEarlyBeanReference(beanName, mbd, bean)判断是否需要AOP,需要返回AOP代理对象,否则返回原始对象
//该逻辑在bean对象实例化后,依赖注入前
this.addSingletonFactory(beanName, () -> {return this.getEarlyBeanReference(beanName, mbd, bean);});
  • 1
  • 2
  • 3

辅助

  1. singletonCurrentlyInCreation
  2. earlyProxyReferences
@Nullable
//从单例池获取bean
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    //判断bean是否在创建中
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
    	//从二级缓存earlySingletonObjects中获取bean对象
        singletonObject = this.earlySingletonObjects.get(beanName);
        //没有获取到bean对象并且允许循环依赖
        if (singletonObject == null && allowEarlyReference) {
            synchronized(this.singletonObjects) {
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                	//从二级缓存earlySingletonObjects中获取bean对象
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                    	//从三级缓存singletonFactories中获取singletonFactory对象
                        ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                        	//执行获取bean对象的逻辑
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }

    return singletonObject;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

初始化后生成的代理对象和循环依赖生成的AOP代理对象不同导致的问题:

//以下逻辑在bean实例化之后
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

			//进行三级缓存
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try {
        	//依赖注入
            this.populateBean(beanName, mbd, instanceWrapper);
            //bean初始化,返回bean对象,如果bean因为AOP以外的代理对象生成,且返回的是该对象
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

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

        if (earlySingletonExposure) {
        	//从单例池拿bean对象,如果因为循环依赖则会从二级缓存中拿到AOP生成的代理对象
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
            	//如果是循环依赖生成的earlySingletonReference,判断exposedObject是否非AOP代理对象
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
					//如果是不同的代理对象,则提示ERROR(避免最后生成的对象不是AOP代理对象,但是循环依赖的BBean依赖注入的是ABean因为AOP生成的代理对象,可以通过在ABean的BBean属性上添加@Laze,则ABean中添加@Async(某些PostProcessor会新生成代理对象,@Transactional不是实现PostProcessor生成代理对象,则不会出现问题)的方法也不会抛出ERROR)
                    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.");
                    }
                }
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

@Lazy解决循环依赖

@Lazy注解会在bean进行依赖注入(以上步骤的第二步)时生成一个代理对象,不会影响bean之后的流程,则不会出现循环依赖。

原型bean循环依赖

原型bean无法解决循环依赖问题。

构造器的循环依赖

无法实例化对应bean则直接提示ERROR,可在构造器加@Lazy解决。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/609284
推荐阅读
相关标签
  

闽ICP备14008679号