Spring IOC 从单例池中获取Bean
概述
在doGetBean方法当中,处理完bename之后,下一步就是尝试从单例池中获取。如果能获取到,那么就对其进行FactoryBean的处理。当然这个处理对于FactoryBean才有用,对应代码如下:
// Eagerly check singleton cache for manually registered singletons.
//如果这里是我们的bean,那么第一次获取肯定是空的,那么这个时候就会走else
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//2.完成FactoryBean的相关处理,并用来获取FactoryBean的处理结果。
//缓存中的bean记录的是最原始的Bean状态,我们得到的不一定是最终想要的bean
//
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
- 这个if选项如果是我们第一次调用这个方法来获取,那么必定通过getSingleton方法返回的对象是空的。那么我们将会进入到else流程中,执行创建Bean的流程。
- 获取到Bean之后,由于FactoryBean的存储方式和普通Bean是一样的,如果这个Bean是FactoryBean的话,要对器进行处理,得到真正的Bean。
getSingleton
//传入的第二个参数就是指是否允许延迟加载
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//第一次调用getSongleton,返回肯定为空
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从三级缓存拿,如果是第一次坑定是拿不到的
singletonObject = this.earlySingletonObjects.get(beanName);
//如果从三级缓存中拿不到,那么判断是否支持循环依赖,再从二级缓存中拿
/**
* 为什么不直接从二级缓存中拿,而是要put到三级缓存中呢
* 性能问题:因为二级缓存是一个工厂,代码相当复杂。从二级缓存中创建出对象的时候进行大量的操作
* 为了避免每次引用这个对象都要使用工厂来创建,就需要使用到三级缓存。
* 既然有性能消耗,那么为什么还要使用工厂呢?
* 解答:因为在前面说过spring的生命周期:
* 1.new
* 2.注入
* 3.执行生命周期方法
* 4.AOP代理
* 5.放入单例池
* 还是循环依赖的场景。如果此时A到了注入的那一步,那么就会进入到B的生命周期。如果这个地方我们不使用工厂
* 那么在B中注入的A就是只执行到第二步的一个A的对象。B的A就不是AOP代理过后的对象。为了解决这个问题使用工厂,因为
* 它可以使这个A的AOP操作提前到这个工厂中来执行。所以说这个工厂的代码也是极其复杂的。为了避免重复执行这里面
* 的代码,这里也用到了三级缓存的。
*/
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);
}
}
}
}
retur