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