Spring源码(4):三级缓存

5,417 阅读6分钟

循环依赖

两个或两个以上对象互相依赖对方,形成一个依赖环,例如A对象依赖B对象,B对象依赖A对象。

image.png 当创建相互依赖的对象时,会形成死循环,例如下图无缓存中的情况。而Spring通过增加缓存,将未完全创建好的A提前暴露在缓存中,当相互依赖的对象B对属性A赋值时,可以直接从缓存中获取A,而不需要再创建A,例如下图有缓存中的情况。

image.png

Spring的三级缓存

Spring的三级缓存分别为:

  • singletonObject:一级缓存,缓存中的bean是已经创建完成的,该bean经历过实例化->属性填充->初始化以及各种的后置处理。因此,一旦需要获取bean时,会优先寻找一级缓存
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) {
         // bean创建前操作,标记当前bean正在创建
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         try {
            // 创建bean
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         catch (Exception ex) {
             // ...
         }
         finally {
            if (recordSuppressedExceptions) {
               this.suppressedExceptions = null;
            }
            // bean创建后操作,删除当前bean正在创建
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            // 存入一级缓存
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

// 在bean创建完成之后,将bean加入到一级缓存中
protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      // 添加一级缓存
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}
  • earlySingletonObjects:二级缓存,该缓存跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化还没有做完,因此该bean还没创建完成,时半成品,仅仅能作为指针提前曝光,被其他bean所引用
// 二级缓存是从三级缓存中通过getObject()方法获取的
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   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) {
                     // 三级缓存通过getObject()方法获取半成品bean
                     singletonObject = singletonFactory.getObject();
                     // 存放二级缓存
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}
  • singletonFactories:三级缓存,在bean实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring会将实例化后的bean提前曝光,也就是把该bean转换成beanFactory并加入到三级缓存。在需要引用提前曝光对象时再通过singletonFactory.getObject()获取。
// 在实例化bean之后,如果允许循环依赖,将未创建完的bean加入到三级缓存
if (earlySingletonExposure) {
   if (logger.isTraceEnabled()) {
      logger.trace("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
   }
   // 存入三级缓存
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

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);
         this.earlySingletonObjects.remove(beanName);
         this.registeredSingletons.add(beanName);
      }
   }
}

三级缓存的使用

当A和B相互依赖时,若先创建实例A,则整个调用过程为:

image.png

其中涉及缓存和依赖相关主要过程为:

  • 开始创建实例A,标记A为正在创建
protected void beforeSingletonCreation(String beanName) {
   // 将实例A加入到singletonsCurrentlyInCreation中
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}
  • 实例化A后,将未赋值和初始化的实例A加入到三级缓存singletonFactories中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

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);
         // 二级缓存删除该bean
         this.earlySingletonObjects.remove(beanName);
         this.registeredSingletons.add(beanName);
      }
   }
}
  • 由于循环依赖,实例A触发实例B加载,标记B为正在创建,并在实例化B后,将未赋值和初始化的实例B加入到三级缓存singletonFactories中(同上)
  • 由于循环依赖,实例B触发实例A加载,在缓存中获取到未创建好的A
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // 一级缓存中不存在A,返回null
   Object singletonObject = this.singletonObjects.get(beanName);
   // A因为已经标记为正在创建,进入下面的if语句
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 二级缓存不存在A,返回null
      singletonObject = this.earlySingletonObjects.get(beanName);
      // 允许循环依赖
      if (singletonObject == null && allowEarlyReference) {
         // 锁定一级缓存和二级缓存,并再次检验
         synchronized (this.singletonObjects) {
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  // 三级缓存中存在未创建好的实例A,获取到ObjectFactory对象
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     // 调用getObject()方法,获取到为创建好的实例A
                     singletonObject = singletonFactory.getObject();
                     // 将实例A放入到二级缓存中
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     // 三级缓存中删除实例A
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}
  • 在B创建好之后,则标记实例B创建完成,并将B加入到一级缓存中
protected void afterSingletonCreation(String beanName) {
   // 将实例B从singletonsCurrentlyInCreation中删除
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
   }
}

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      // 将实例B放入一级缓存
      this.singletonObjects.put(beanName, singletonObject);
      // 三级缓存中删除B
      this.singletonFactories.remove(beanName);
      // 二级缓存中删除B
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}
  • 在A创建好之后,则标记实例A创建完成,并将A加入到一级缓存中

AOP和三级缓存

不涉及AOP

实例加入到三级缓存,并从三级缓存中获取实例过程如下:

// 添加到三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

// 使用三级缓存
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
   singletonObject = singletonFactory.getObject();
   this.earlySingletonObjects.put(beanName, singletonObject);
   this.singletonFactories.remove(beanName);
}

从三级缓存获取到的bean,是经过getEarlyBeanReference()作用之后返回的bean,在不涉及AOP时,没有类覆盖实现getEarlyBeanReference()方法,使用getEarlyBeanReference()的默认实现,因此返回的bean就是实例化后的原始bean。

default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
   return bean;
}

涉及AOP

当涉及到AOP时,AbstractAutoProxyCreator实现了getEarlyBeanReference()方法,返回的bean是经过AOP代理的bean。

public Object getEarlyBeanReference(Object bean, String beanName) {
   Object cacheKey = getCacheKey(bean.getClass(), beanName);
   this.earlyProxyReferences.put(cacheKey, bean);
   // 创建AOP代理
   return wrapIfNecessary(bean, beanName, cacheKey);
}

不涉及循环依赖时,bean的AOP代理是在实例化,赋值,初始化之后创建的。而涉及循环依赖时,三级缓存中保存的是实例化但未赋值,初始化之后的bean,当通过三级缓存获取实例时,则会提前创建AOP代理:

  • 非循环依赖,在实例化,赋值,初始化之后创建AOP代理
  • 循环依赖,在实例化,未赋值,初始化之后创建AOP代理(提前创建代理)

对于在缓存中提前创建好代理的实例,当赋值,初始化之后,运行至bean的后置处理逻辑,即AbstractAutoProxyCreator的postProcessAfterInitialization方法(正常创建AOP代理逻辑)时,则不会再次创建AOP代理,返回的是不经代理的bean。

// AbstractAutoProxyCreator的后置处理逻辑
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      // 由于提前创建了代理并且有缓存,则不再返回代理
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

再返回赋值和初始化bean的逻辑中,exposedObject作为最终的返回结果,在使用到AOP时,最终返回的都是代理bean

// 原始bean
Object exposedObject = bean;
try {
   // 实例赋值
   populateBean(beanName, mbd, instanceWrapper);
   // 实例初始化(初始化后调用bean的后置处理逻辑,即创建AOP代理)
   // (1)非循环依赖,未提前创建代理,initializeBean返回的是代理bean
   // (2)循环依赖,提前创建代理,initializeBean返回的是原始bean
   exposedObject = initializeBean(beanName, exposedObject, mbd);
}

if (earlySingletonExposure) {
   // 当allowEarlyReference=false时,只能从一级二级缓存中获取实例
   // (1)未提前创建代理时,实例在三级缓存中,getSingleton返回代理null
   // (2)提前创建代理时,实例在二级缓存中,返回代理bean
   Object earlySingletonReference = getSingleton(beanName, false);
   if (earlySingletonReference != null) {
      // 提前创建代理,代理bean在缓存中,所以下面相等
      if (exposedObject == bean) {
         // 将代理bean赋值给exposedObject
         exposedObject = earlySingletonReference;
      }
      // ...
   }
}