Spring 三级缓存

Spring 三级缓存

createBean过程中,会去判断需要的Bean 是否是单例的、是否允许是循环依赖的(默认是的)、是否是 正在创建中的。条件都满足,会将该 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");
  }
  addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

在Spring程序中,定义以下类:

@Service("aService")
public class AService {
	@Autowired
	BService bService;
}


@Service("bService")
public class BService {
	@Autowired
	AService aService;
}

debug

在spring加载过程中,扫描到需要放入 ioc 容器的beanNames ,会去循环遍历这些 beanNames 然后将他们创造成一个个 Bean

// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
  RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    if (isFactoryBean(beanName)) {
      // 是否是个 FactoryBean 这里进不来
    }
    else {
      getBean(beanName);
    }
  }
}

以 AService 这个类 创建的过程为例:

getBean(beanName)-->doGetBean(...)-->getSingleton(beanName)--->getSingleton(beanName,false)

最终来到 getSingleton(String beanName, boolean allowEarlyReference) 这个方法

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  // beanName = aService 	allEarlyReference=false
  // Quick check for existing instance without full singleton lock
  // 从一级缓存获取 bean	获取到直接返回
  Object singletonObject = this.singletonObjects.get(beanName);	// null
  // isSingletonCurrentlyInCreation(beanName) true
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {	
    //第一次getSingleton 并不是在创建中,所以会直接返回空
    // 不是在创建中,并且一级缓存还没有这个 aservice,那么就要 createBean
    // 第一次不会走到这里,代码省略    .....
  }
  return singletonObject;
}

没有获取到,那 spring 就会创建一个,代码会来到这里 执行 createBean

// Create bean instance.
if (mbd.isSingleton()) {
  sharedInstance = getSingleton(beanName, () -> {
    try {
      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;
    }
  });
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

进入到 DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory) 这个方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
  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放入正在创建的 这样一个set 集合里面
      //this.singletonsCurrentlyInCreation.add(beanName)
      beforeSingletonCreation(beanName);
      // 接下来就是一系列判断
      boolean newSingleton = false;
      boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
      if (recordSuppressedExceptions) {
        this.suppressedExceptions = new LinkedHashSet<>();
      }
      try {
        // 这个方法,传进来的是一个 lamda,会跳回,执行 lamda 里面的方法:
        //  return createBean(beanName, mbd, args); 这个方法里面调用的 doCreateBean
        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;
  }
}

doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

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

  // Instantiate the bean.
  BeanWrapper instanceWrapper = null;
  if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  }
  if (instanceWrapper == null) {
    instanceWrapper = createBeanInstance(beanName, mbd, args);
  }
  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 {
        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));
  // 这时候 aService 就在创建当中,会放入 三级缓存 (第三级缓存)
  if (earlySingletonExposure) {
    if (logger.isTraceEnabled()) {
      logger.trace("Eagerly caching bean '" + beanName +
                   "' to allow for resolving potential circular references");
    }
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  }

  // 到这里,aService 就已经实例化好了,接下来就是 填充属性了
  // Initialize the bean instance.
  Object exposedObject = bean;
  try {
    // 会给 aService填充属性,由于aService里面依赖了bService,肯定是去获取,获取不到,再创建
    //故再走一遍 getBean bService 的逻辑
    // 最开始 bService 在一级缓存也没有,并且也不是在创建中直接返回了一个null,并且 bService也没有在创建中,所以我们要开始 ceateBean(bService) 并标记 bService 正在创建中,在doCreateBean中,将 bService 也加入了 三级缓存 这时候 三级缓存有 aService bService 创建完了之后,就该填充 bService 的属性了,由于 bService 又依赖了 aService,我们会去执行 getSingleton(aService)
    populateBean(beanName, mbd, instanceWrapper);
    // ceate bService 要去填充 aService 的属性,这时候已经在三级缓存找到了,就填好了
    // 接下来就是 bService 的 生命周期剩下的事
    // 初始化 bService,执行工厂回调方法、 init方法、和 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) {	//true
    // getSingleton 从一级缓存、二级缓存都没找到,传了个 false,直接返回null 了
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
      // 进不来 省略了。。。。
    }

    // Register bean as disposable.
    try {
      // 注册 bService
      // 判断是否是 propertype 以及 是不是在关闭时候需要销毁 这里 bService 并没有设置,
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
  }

我们又来到了 DefaultSingletonBeanRegistry.getSingleton(String beanName, boolean allowEarlyReference)这个方法里面

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  // Quick check for existing instance without full singleton lock
  // 一级缓存还是没有,下一步
  Object singletonObject = this.singletonObjects.get(beanName);
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    // 由于之前已经标志 aService 正在创建中,所以能走到这里
    // 从二级缓存获取
    singletonObject = this.earlySingletonObjects.get(beanName);
    if (singletonObject == null && allowEarlyReference) {
      // 二级缓存也没有,并且是支持循环依赖的(默认就支持)
      // 这里可能是 spring 为了方法复用,加了一些重复的代码,具体也不知道为什么 ,下面加锁的才是我们现在这个流程需要的代码
      synchronized (this.singletonObjects) {
        // Consistent creation of early reference within full singleton lock
        // 一级缓存 singletonObjects
        singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
          // 二级缓存 earlySingletonObjects
          singletonObject = this.earlySingletonObjects.get(beanName);
          if (singletonObject == null) {
            // 三级缓存 ObjectFactory	
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
              // 从三级缓存里面肯定会获取到,之前已经把 aService 加入了三级缓存嘛
              singletonObject = singletonFactory.getObject();			// 执行 lamda,AOP
              // 这里调用singletonFactory.getObject() 会去执行 当初加入时候那个 lamda 表达式里面的代码:getEarlyBeanReference(beanName, mbd, bean)
              // 放入二级缓存,并把它从三级缓存删掉
              this.earlySingletonObjects.put(beanName, singletonObject);
              this.singletonFactories.remove(beanName);	// 防止重复创建 aop 代理对象
            }
          }
        }
      }
    }
  }
  return singletonObject;
}
Object sharedInstance = getSingleton(beanName);	// 第一次 getSingleton 的时候返回空
if (sharedInstance != null && args == null) {
  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 + "'");
    }
  }
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
posted @ 2022-01-14 08:57  jalivv  阅读(739)  评论(0)    收藏  举报