缓存中获取单例bean

单例是只创建一次,先从缓存中取。当然这里是尝试加载,首先尝试从缓存中取,如果失败再从singletonFactories中加载。因为在创建bean的时候存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会创建Bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory。

我们来看一下getSingleton方法:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 检查缓存中是否存在实例
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 如果没有在单例列表中,并且在正在创建的列表中
        // 锁定全局变量开始处理
        synchronized (this.singletonObjects) {
            // 去早期引用的列表找是否存在
            // 如果这个bean正在加载则不处理
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 不存在并且允许早期引用
                // 当某些方法需要提前初始化的时候则会调用,addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 调用预先设定的getObject方法
                    singletonObject = singletonFactory.getObject();
                    // 记录在缓存中,向earlySingletonObjects加入,从singletonFactories移除
                    // earlySingletonObjects和singletonFactories互斥
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

这个方法因为涉及循环依赖的检测,以及涉及很多变量的记录存取,所以很难读懂。它首先从singletonObjects中尝试获取实例,没有再从earlySingletonObjects获取,还没有再从singletonFactories获取对应的ObjectFactory,然后调用ObjectFactory#getObject方法来创建bean,并放到earlySingletonObjects中,再从singletonFactories删除。而对于后续的所有内存操作都只是为了循环依赖检测的时候用,也就是在allowEarlyReference为true的情况下才会使用。

这里涉及用于存储bean的不同map,下面来解析一下:

  1. singletonObjects:用于保存BeanName和创建bean实例之间的关系
  2. singletonFactories:用于保存beanName和创建bean工厂之间的关系。
  3. earlySingletonObjects:也是保存beanName和创建bean实例之间的关系,与singletonObjects的不同在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是为了检测循环依赖。
  4. registeredSingletons:用来保存当前所有已注册的Bean。

results matching ""

    No results matching ""