5.2:缓存中获取单例bean

5.2  缓存中获取单例bean

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

 

 

 1 public Object getSingleton(String beanName) {
 2      //参数true设置标识允许早期依赖    
 3     return getSingleton(beanName, true);
 4 }
 5 
 6 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 7          //检查缓存中是否存在实例
 8          Object singletonObject = this.singletonObjects.get(beanName);
 9          if (singletonObject == null) {
10              //如果为空,则锁定全局变量并进行处理
11              synchronized (this.singletonObjects) {
12                  //如果此bean正在加载则不处理
13                  singletonObject = this.earlySingletonObjects.get(beanName);
14                  if (singletonObject == null && allowEarlyReference) {
15                      //当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
16                      ObjectFactory singletonFactory = this.singletonFactories.get (beanName);
17                      if (singletonFactory != null) {
18                          //调用预先设定的getObject方法
19                          singletonObject = singletonFactory.getObject();
20                          //记录在缓存中,earlySingletonObjects和singletonFactories互斥
21                          this.earlySingletonObjects.put(beanName, singletonObject);
22                          this.singletonFactories.remove(beanName);
23                      }
24                  }
25              }
26          }
27          return (singletonObject != NULL_OBJECT ? singletonObject : null);
28      }

 

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

 

 

 

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

 

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

 

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

 

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

 

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

 

 

 

原文地址:https://www.cnblogs.com/mjorcen/p/3582999.html