Spring源码解析-三级缓存与循环依赖,nginx架构图

  • Post author:
  • Post category:其他


两个流程理论上是互不影响的


protected <T> T doGetBean(

      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)

      throws BeansException {

    // bean名称转换

    // 根据指定的名称获取被管理bean的名称

    // 如果指定是别名,将别名转换为规范的Bean名称

    String beanName = transformedBeanName(name);

    Object bean;

​

    // 从各级缓存中获取bean对象

    Object sharedInstance = getSingleton(beanName);

    // 这个判断是跟factoryBean相关的

    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);

    }

​

    ......

​

        // 创建bean对象

        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);

        }

​

        ......

    // 返回bean对象

    return (T) bean;

  }

我们重点看两个getSingleton()方法


// 这段代码三级缓存容器都涉及到了,初看有点懵,但是思路不难,先从一级缓存找,找不到去二级缓存找,还找不到去三级缓存

// 如果在三级缓存找到了,就放到二级缓存中,非常像数据库跟redis的缓存策略,先到redis中找,找不到去数据库找,找到再写到redis中

protected Object getSingleton(String beanName, boolean allowEarlyReference) {

    // 先从一级缓存中找bean

    Object singletonObject = this.singletonObjects.get(beanName);

    // 这里有两个判断,singletonObject == null 表示在一级缓存中找不到bean

    // isSingletonCurrentlyInCreation()表示该bean是否在创建中

    // 如果两个条件满足,说明出现了循环依赖

    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

      synchronized (this.singletonObjects) {

        // 再从二级缓存中获取

        singletonObject = this.earlySingletonObjects.get(beanName);

        // 这里又有两个判断

        // singletonObject == null 表示在二级缓存中没有获取到

        // allowEarlyReference 这个值传进来就为true,表示是否允许获取早期引用

        // 如果两个条件都满足,就到三级缓存中获取

        if (singletonObject == null && allowEarlyReference) {

          // 从三级缓存获取,注意,这里获取到是一个ObjectFactory

          ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);

          if (singletonFactory != null) {

            // 通过ObjectFactory获取bean实例

            singletonObject = singletonFactory.getObject();

            // 打怪升级,从三级缓存升级到二级缓存,

            this.earlySingletonObjects.put(beanName, singletonObject);

            this.singletonFactories.remove(beanName);

          }

        }

      }

    }

    // 返回bean

    return singletonObject;

  }

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {

Assert.notNull(beanName, "Bean name must not be null");

synchronized (this.singletonObjects) {

// 从一级缓存中获取bean

  Object singletonObject = this.singletonObjects.get(beanName);

// 如果bean为空

  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创建前会将这个bean放到一个容器中,标志这个bean正在创建中

    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) {

      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;

      }

// 单例bean创建完成后,会把bean从这个容器中移除

      afterSingletonCreation(beanName);

    }

// newSingleton为true时,表示bean创建成功

    if (newSingleton) {

// 把bean放到一级缓存中,一级缓存就是我们常说的IOC容器

      addSingleton(beanName, singletonObject);

    }

  }

  return singletonObject;

}

}


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);

    }

}

```



从上面的代码我们已经可以总结出bean没有出现循环依赖时,流程是怎么样的?



1.  getSingleton()方法查看是否存在于一级缓存中,是则获取,无则走下面的创建流程,因为没有出现循环依赖,isSingletonCurrentlyInCreation(beanName),此判断是false

2.  createBean()方法创建一个bean

3.  addSingleton()方法将bean放到一级缓存中



当然,在正常的流程中会穿插异常流程的处理方式,比如bean创建前会把bean放到一个容器中,Spring凭借这个可以知道bean是否正在创建中,得知bean在创建中后,会利用三级缓存获得bean空壳



```

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

      throws BeanCreationException {

​

    ....

​

    // mbd.isSingleton():bean是否是单例

    // this.allowCircularReferences:是否允许出现循环依赖

    // isSingletonCurrentlyInCreation(beanName):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");

      }

      // 将bean放到三级缓存中

      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

    }

​

    // Initialize the bean instance.

    Object exposedObject = bean;

    try {

      // 属性赋值

      populateBean(beanName, mbd, instanceWrapper);

      // 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) {

      // 从各级缓存中获取bean,getSingleton(beanName, false)这个方法是不是很熟悉,上面已经使用到了

      // 只是第二个参数从true变成了false,这个参数决定了要不要从第三级缓存中获取数据

      // 代码走到这个地方,已经无需获取早期引用了,所以参数为false

      Object earlySingletonReference = getSingleton(beanName, false);

      // 如果二级缓存不为空

      if (earlySingletonReference != null) {

        // 并且二级缓存中的bean跟exposedObject相等,说明初始化时,没有使用代理修改bean对象

        if (exposedObject == bean) {

          // 直接将二级缓存中bean返回即可

          exposedObject = earlySingletonReference;

        }

    ....

​

    return exposedObject;

  }

```



我们重点看看addSingletonFactory()这个方法,我们先看一段简单代码,感受一下ObjectFactory这个类的作用



```

public class ObjectFactoryTest {

​

​

    public static void main(String[] args) {

        HashMap<String, ObjectFactory<?>> map = new HashMap<>(2);

        map.put("a", () -> {

            System.out.println("objectFactory");

            return "string";

        });

​

        System.out.println(map.get("a").getObject());

    }

}

```



![image.png](https://img-blog.csdnimg.cn/img_convert/0a437e603e6bbb7208ac92b516a6703c.png) 原来,ObjectFactory可以定制执行方法,那么Spring要定制的执行方法是什么?



```

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);

      }

    }

}

// 要定制的执行方法就是一个beanPostProcess的埋点

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {

Object exposedObject = bean;

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

  for (BeanPostProcessor bp : getBeanPostProcessors()) {



最后



送大家一个小福利,点击领取Java全套进阶资料

etons.add(beanName);

  }

}

}


// 要定制的执行方法就是一个beanPostProcess的埋点

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {

    Object exposedObject = bean;

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

      for (BeanPostProcessor bp : getBeanPostProcessors()) {


# 最后

**[送大家一个小福利,点击领取Java全套进阶资料](https://gitee.com/vip204888/java-p7)**

[外链图片转存中...(img-60Y6qU4z-1628591179093)]

[外链图片转存中...(img-cR7POWt5-1628591179096)]

![](https://img-blog.csdnimg.cn/img_convert/75d03bc41b86865b384048958c2070a0.png)



版权声明:本文为m0_54926105原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。