返回介绍

5.2 缓存中获取单例 bean

发布于 2025-04-22 22:09:10 字数 2409 浏览 0 评论 0 收藏

介绍过 FactoryBean 的用法后,我们就可以了解 bean 加载的过程了。前面已经提到过,单例在 Spring 的同一个容器内只会被创建一次,后续再获取 bean 直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试尝试从 singletonFactories 中加载。因为在创建单例 bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖, Spring 创建 bean 的原则是不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提早曝光加入到缓存中,一旦下一个 bean 创建时需要依赖上个 bean,则直接使用 ObjectFactory。

public Object getSingleton(String beanName) {

 //参数 true 设置标识允许早期依赖

return getSingleton(beanName, true);

}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {

 //检查缓存中是否存在实例

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

  if (singletonObject == null) {

  //如果为空,则锁定全局变量并进行处理

   synchronized (this.singletonObjects) {

   //如果此 bean 正在加载则不处理

    singletonObject = this.earlySingletonObjects.get(beanName);

    if (singletonObject == null && allowEarlyReference) {

    //当某些方法需要提前初始化的时候则会调用 addSingletonFactory 方法将对应

    的 ObjectFactory 初始化策略存储在 singletonFactories

    (beanName);

     ObjectFactory singletonFactory = this.singletonFactories.get

     if (singletonFactory != null) {

     //调用预先设定的 getObject 方法

      singletonObject = singletonFactory.getObject();

     //记录在缓存中,earlySingletonObjects 和 singletonFactories 互斥

      this.earlySingletonObjects.put(beanName, singletonObject);

     this.singletonFactories.remove(beanName);

    }

   }

  }

 }

  return (singletonObject != NULL_OBJECT ? singletonObject : null);

}

这个方法因为涉及循环依赖的检测,以及涉及很多变量的记录存取,所以让很多读者摸不着头脑。这个方法首先尝试从 singletonObjects 里面获取实例,如果获取不到再从 earlySingleton Objects 里面获取,如果还获取不到,再尝试从 singletonFactories 里面获取 beanName 对应的 ObjectFactory,然后调用这个 ObjectFactory 的 getObject 来创建 bean,并放到 earlySingleton Objects 里面去,并且从 singletonFacotories 里面 remove 掉这个 ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在 allowEarlyReference 为 true 的情况下才会使用。

这里涉及用于存储 bean 的不同的 map,可能让读者感到崩溃,简单解释如下。

singletonObjects:用于保存 BeanName 和创建 bean 实例之间的关系,bean name --> bean instance。

singletonFactories:用于保存 BeanName 和创建 bean 的工厂之间的关系,bean name -->ObjectFactory。

earlySingletonObjects:也是保存 BeanName 和创建 bean 实例之间的关系,与 singletonObjects 的不同之处在于,当一个单例 bean 被放到这里面后,那么当 bean 还在创建过程中,就可以通过 getBean 方法获取到了,其目的是用来检测循环引用。

registeredSingletons:用来保存当前所有已注册的 bean。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。