美文网首页
spring循环依赖

spring循环依赖

作者: 卫渐行 | 来源:发表于2020-03-07 17:38 被阅读0次

Spring 循环依赖

什么是循环依赖

概念: 在代码中对象A依赖对象B,对象B依赖对象A,对象相互之间依赖关系;

Class A{
 private B b;
}
Class B{
private A a;
}

Spring能解决什么情况下的依赖

  • Spring单例对象的属性之间形成的循环依赖
Class A {
B b ;
private setB(B b){
this.b=b;
}
}

Spring不能解决循环依赖的情况

  • 原型的依赖,因为已经委托给容器管理
  • 单例的构造器注入;(Spring在refresh()初始化bean对象过程中,需要创建一个Springbean,然后注入其对象)

Spring如何解决的单例的循环依赖问题

三个缓存对象

1:在DefaultSingletonBeanRegistry 单例的注册中心有三个缓存的对象:
  • singletonObjects 对象的一级缓存,创建完成后的对象,都在该对象中;
  • singletonFactories 单例bean的三级缓存;单例对象工厂的cache,第一次创建的bean单例对象,在第一次创建过程都会现在此缓存一下;
  • earlySingletonObjects 提前曝光的单例对象(对象在进行属性注入的时候,获取到singletonFactories中的对象,会将singletonFactories 中的对象,缓存到earlySingletonObjects中去)
2 源码分析
  • 先分析获取单例对象时候,先从缓存中拿到单例对象
@Nullable
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);//判断三级缓存中是否存在bean对象
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();//从三级缓存中取出数据的时候,需要将bean对象转换成器代理对象,
               this.earlySingletonObjects.put(beanName, singletonObject);//如果三级缓存中存在,吧bean 对象加入到二级缓存中
               this.singletonFactories.remove(beanName);//移除三级缓存中的数据
            }
         }
      }
   }
   return singletonObject;
}

通过上述代码,非常清晰的告诉读者;在单例的对象创建之前,都会先从一级缓存的singletonObjects获取对象;

如果一级缓存中没有,从earlySingletonObjects 提前曝光的二级缓存中获取对象;

  • 在创建bean 开始之前,还会在判断一次缓存中,对象是否存在,从singletonObjects 和 singletonFactories缓存中获取;

    /**
     * Return the (raw) singleton object registered under the given name,
     * creating and registering a new one if none registered yet.
     * @param beanName the name of the bean
     * @param singletonFactory the ObjectFactory to lazily create the singleton
     * with, if necessary
     * @return the registered singleton object
     */
    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 (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName,
                      "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                      "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
             }
             if (logger.isDebugEnabled()) {
                logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
             }
             //验证完 要真正开始创建对象,先从标识该bean正在被创建,因为Springbean创建过程复杂,步骤很多,需要标识
             beforeSingletonCreation(beanName);
             boolean newSingleton = false;
             boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
             if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
             }
             try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
             }
             catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                   throw ex;
                }
             }
             catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                   for (Exception suppressedException : this.suppressedExceptions) {
                      ex.addRelatedCause(suppressedException);
                   }
                }
                throw ex;
             }
             finally {
                if (recordSuppressedExceptions) {
                   this.suppressedExceptions = null;
                }
                afterSingletonCreation(beanName);
             }
             if (newSingleton) {
                addSingleton(beanName, singletonObject);
             }
          }
          return singletonObject;
       }
    }
    

    单例对象在第一次创建的时候,都会将单例对象bean,先放在singletonFactories当中

      /**
       * Add the given singleton factory for building the specified singleton
       * if necessary.
       * <p>To be called for eager registration of singletons, e.g. to be able to
       * resolve circular references.
       * @param beanName the name of the bean
       * @param singletonFactory the factory for the singleton object
       * 
       *
       */
    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);//加入三级缓存,所以现在singletonFactory,
             this.earlySingletonObjects.remove(beanName);//并从二级缓存中删除
             this.registeredSingletons.add(beanName);
          }
       }
    }
    

总结:根据上述的源代码,getSingleton和addSingletonFactory ,知道了三个缓存中的转换关系;如果A依赖B,B依赖A

  • A对象第一次创建,先执行getSingleton()方法 bean对象会返回为空,在执行addSingletonFactory(),正在创建的bean会先放在singletonFactories 中

  • 因为A依赖B,在处理A的成员变量B的创建过程中,B,也是先执行getSingleton()方法 bean对象会返回为空,在执行addSingletonFactory(),正在创建的bean会先放在singletonFactories 中

  • 所以此时 singletonFactories 中存在两个正在创建的bean,A 和B;

  • 因为B同样依赖A,B的属性依赖A的对象,在创建的时候,先执行getSingleton(),很清楚的发现

    if (singletonFactory != null) {
                   singletonObject = singletonFactory.getObject();//从三级缓存中取出数据的时候,需要将bean对象转换成器代理对象,
                   this.earlySingletonObjects.put(beanName, singletonObject);//如果三级缓存中存在,把bean 对象加入到二级缓存中
                   this.singletonFactories.remove(beanName);//移除三级缓存中的数据
                }
    

    此时对象A从singletonFactory 中取出,并加入到earlySingletonObjects 缓存当中去;并将对象返回;

  • B对象依赖的成员变量A 在创建过程中,在三级缓存中获取得到了对象A,并将其缓存到二级对象earlySingletonObjects中,然后此时回调;B对象先完成创建,并将B对象放在一级缓存(singletonObjects)中

  • B对象,完成initializeBean(aware接口实现,init方法实现,beanpostprocessor实现)完成创建,回溯到A对象中的属性B完成创建

  • A对象的其它属性创建成功,A对象最后从二级缓存中获取到A的对象,放在一级缓存当中

Spring调用栈的时序图

分析spring 解决循环依赖问题,需要主要上面的几个流程,同时把握Spring 源码在初始化Spring bean对象的过程;

  • refresh()方法 abstractApplicationContext的方法,bean对象初始化的入口
  • finishBeanFactoryInitialization() bean 对象创建的入口方法
  • preInstantiateSingletons() ,加载bean对象的RootBeanDefinition,并且开始getBean(),注意bean的动态的代理对象也是再次获取

下面是具体的时序图;有待完善,只记录自己的学习过程


时序图.png

相关文章

网友评论

      本文标题:spring循环依赖

      本文链接:https://www.haomeiwen.com/subject/tpqhdhtx.html