分析:org.springframework.beans.factory.support.AbstractBeanFactory中
doGetBean的方法:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException
从缓存中获取bean的代码块如下:
1. transformedBeanName(name)
final String beanName = transformedBeanName(name);
transformedBeanName方法如下:
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils.transformedBeanName(name) 方法如下:
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
-- 如果 name 不是以 & 开头的 直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
-- 如果 name 是以 & 开头的,截取掉&,再返回
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
public String canonicalName(String name) 代码如下:
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
-- aliasMap 缓存的是 别名的 集合
-- 这里将传递的别名转换为 真正的名字
-- 如果没有别名,则直接返回
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
综上:final String beanName = transformedBeanName(name); 的功能是先截取掉&(如果有的话),并通过别名(如果传递的参数为别名)找到真正的名字。
接下来:从缓存获取bean:重点
代码如下: Object sharedInstance = getSingleton(beanName);追踪进去,发现再 DefaultSingletonBeanRegistry.java 类中有:
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
再次追踪进去:
//
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
1. 该方法的作用是:返回给定名字的已经注册过的原始的单例实例
2. singletonObjects是个map, 缓存的是的 单例的名字->单例对象,Object singletonObject = this.singletonObjects.get(beanName); 是从缓存中获取单例。
3. 如果缓存中没有对象,并且该beanName是要当前要创建的单例的名字,
isSingletonCurrentlyInCreation(beanName) 解释见下面
/**
* Return whether the specified singleton bean is currently in creation
* (within the entire factory).
* @param beanName the name of the bean
*/
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
这里:singletonsCurrentlyInCreation 缓存的当前要创建的Bean的所有的名字
/** Names of beans that are currently in creation. */
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
4. synchronized (this.singletonObjects) 锁定全局变量,防止并发问题出现
5. singletonObject = this.earlySingletonObjects.get(beanName); earlySingletonObjects 缓存的早期的单例对象,(beanName -> bean)
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
为什么会有这个判断:如果这个Bean正在加载,则不处理
7. if (singletonObject == null && allowEarlyReference) 如果当前的bean不是正在加载,并且 允许早期的引用创建 (allowEarlyReference whether early references should be created or not,allowEarlyReference的作用:是否应该创建早期的引用 early references)这里为true,为了解决循环依赖的问题
8. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);singletonFactories 缓存的是单例工厂,(beanName -> ObjectFactory)代码如下。 当某些地方需要提前初始化的时候则会调用 addBeanFactory方法将对应的ObjectFactory初始化策略存储再singletonFactories 中
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
9. 如果单例工厂不为空,从工厂获取对象,再将获取到的对象缓存到earlySingletonObjects中,再将单例工厂移除singletonFactories。
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
回到文章最开始doGetBean的方法:
代码先贴出来:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
如果缓存中获取到了对象,并且没有参数:那么执行
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
为什么有这行代码:getObjectForBeanInstance使用的频率很高,无论是从缓存中加载bean还是根据不同的scope策略加载bean。总之,我们得到bean的实例后要做的第一件事情就是调用这个方法来检测一下正确性,其实就是检测当前bean是否是FactoryBean类型的Bean,如果是,那么需要调用该bean对应的FactoryBean的getObject()的方法作为返回值。
无论是从缓存中加载bean还是根据不同的scope策略加载bean,都只是最原始的bean状态,并不一定是我们想要的Bean。例如:我们都对需要对工厂bean进行处理,那么这里得到的其实是工程bean的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法中的返回的bean,而getObjectForBeanInstance方法就是完成这个工作。
接下来分析这行代码:
通过方法的描述我们知道:该方法可能返回bean本身,也可能返回bean对应的FactoryBean,具体看源码分析:
下面我们看上图的最后一个方法:
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
方法的描述是:从暴露出来的指定的FactoryBean中获取对象
源码分析如下图:
分析doGetObjectFromFactoryBean方法:这个逻辑比较简单。
再次分析 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) 这个方法:
spring再获取到object对象之后,并没有直接返回,而是做了后续处理,调用了 object = postProcessObjectFromFactoryBean(object, beanName); 方法,代码如下:
分析源码如下:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.java
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
我们发现,这里是对获取到的object对象坐的后续处理。实际调用的postProcessAfterInitialization方法,在实际开发中可以针对此特性设计自己的业务逻辑。
到这里把bean加载的第一步完成了。