protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
/**
* 1. 转换beanName,存在一下2种情况
* 1.当获取的是工厂而非bean时,beanName会带上&,此时需要先去掉&
* 2.如果是别名,将别名转化为真实的beanName
*/
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 2. 尝试从缓存中获取bean
Object sharedInstance = getSingleton(beanName);
// 这节我们只关心第二点,因此后面先暂时注释掉
...
}
1. 转换为真实beanName(先回顾一下)
由于传入的beanName
可能带&前缀
需要获取工厂,也有可能是别名
。因此需要做以下转换,找出真实的beanName
protected String transformedBeanName(String name) {
// 先调用transformedBeanName去除前缀,再调用canonicalName替换别名
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// 去除前缀
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// FACTORY_BEAN_PREFIX = "&",不包含&前缀直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
// 去除FACTORY_BEAN_PREFIX前缀,知道不包含前缀
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
// 替换别名
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 通过aliasMap获取beanName,直到不再有别名
resolvedName = this.aliasMap.get(canonicalName);
// 可能存在A->B->C->D,所以需要一直循环直到没有别名位置
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
2. 从缓存中获取bean
// AbstractBeanFactory.java
// 2. 尝试从缓存中获取bean
Object sharedInstance = getSingleton(beanName);
这里我将缓存分为三级:
-
singletonObject
:一级缓存,该缓存key = beanName, value = bean;
这里的bean是已经创建完成的,该bean经历过实例化->属性填充->初始化以及各类的后置处理。因此,一旦需要获取bean时,我们第一时间就会寻找一级缓存 -
earlySingletonObjects
:二级缓存,该缓存key = beanName, value = bean;
这里跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化肯定还没有做完,因此该bean还没创建完成,仅仅能作为指针提前曝光,被其他bean所引用 -
singletonFactories
:三级缓存,该缓存key = beanName, value = beanFactory;
在bean实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring会将实例化后的bean提前曝光,也就是把该bean转换成beanFactory
并加入到三级缓存。在需要引用提前曝光对象时再通过singletonFactory.getObject()
获取 -
registeredSingletons
:保存着所有注册过单例的beanName
,是一个set确保不重复
// DefaultSingletonBeanRegistry.java
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存获取,key=beanName value=bean
Object singletonObject = this.singletonObjects.get(beanName);
// singletonObject为空,且该bean正在创建中(假设不在创建中那么肯定是还没被实例化以及提前曝光的,继续查找没有意义)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存获取,key=beanName value=bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 是否允许循环引用
if (singletonObject == null && allowEarlyReference) {
// 从缓存中获取BeanFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 通过getObject()方法获取bean,获取到的实例不单单是提前曝光出来的实例,它还经过了SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法处理过。这也正是三级缓存存在的意义,用户可以通过重写该后置处理器对提前曝光的实例进行一些操作
singletonObject = singletonFactory.getObject();
// 将三级缓存生产的bean放入二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 删除三级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
拓展:三级缓存相关方法
为了让大家对三级缓存有更深的理解,我们看看三级缓存都是怎么被使用的
addSingleton
:添加单例缓存,当bean被创建完以后进行的操作。这时候说明bean已经创建完,删除二三级缓存,直接留下一级缓存,并且注册该bean
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// bean创建完毕,删除二三级缓存,留下以一级缓存。
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
// 注册当前beanName
this.registeredSingletons.add(beanName);
}
}
addSingletonFactory
:添加单例工厂缓存,也就是添加三级缓存
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
// 只有一级缓存不存在的情况下,才会尝试缓存singletonFactory(三级缓存)
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
removeSingleton
:移出单例,则全部缓存一起清空
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
containsSingleton
:查询bean是否在一级缓存中
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
clearSingletonCache
:清空缓存,则把所有的缓存都clear掉,请勿混淆clear跟remove
protected void clearSingletonCache() {
synchronized (this.singletonObjects) {
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
}
}