核心成员变量
DefaultSingletonBeanRegistry:
/**
* Cache of singleton objects: bean name to bean instance.
* <p>单例对象的高速缓存:beam名称-bean实例,所有bean对象最终都会放到对象中</p>
* */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* Cache of singleton factories: bean name to ObjectFactory.
* <p>单例工厂的缓存:bean名称 - ObjectFactory </p>
* */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* Cache of early singleton objects: bean name to bean instance.
* <p>早期单例对象的高速缓存:bean名称 - bean实例</p>
* <p>当从singletonFactories中获取到对应对象后,就会放到这个缓存中</p>
* */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
用例
假设 A 依赖 B,B又依赖 A
步骤解释
- 将A的Bean名添加singletonsCurrentlyInCreation中表明起正在创建。使用A对应的 ObjectFactory 对象来创建A的对象.
具体代码:
DefaultSingletonBeanRegistry # getSingleton(String beanName, ObjectFactory<?> singletonFactory)
...
// 创建单例之前的回调,默认实现将单例注册为当前正在创建中
// 将beanName添加到 当前正在创建的bean名称列表【singletonsCurrentlyInCreation】后
beforeSingletonCreation(beanName);
try {
//从单例工厂中获取对象,singletonFactory其实就是调 AbstractBeanFactory#createBean方法
// 创建出singletonObject
singletonObject = singletonFactory.getObject();
//生成了新的单例对象的标记为true,表示生成了新的单例对象
newSingleton = true;
}
- 实例化 A 的对象
具体代码:
AbstractAutowireCapableBeanFactory # doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
...
//如果包装对象获取失败
if (instanceWrapper == null) {
//使用适当的实例化策略为指定的BeanName创建一个新实例:工厂方法,
// 构造函数自动装配或简单实例化。
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
/获取 instanceWrapperd包装的实例,此时还不算是Bean对象,只有最终加入了singletonObjects才算是Bean对象,这里是
// 只是算是beanName对应的实例对象
final Object bean = instanceWrapper.getWrappedInstance();
...
- 将A的对象再次封装到一个新的ObjectFactory对象,添加到 singletonFactories 中
具体代码:
AbstractAutowireCapableBeanFactory # doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
···
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 饿汉式缓存 单例能够解决 循环依赖,即使被生命周期接口触发。
// 单例饿汉式暴露的情况标记 = 如果mdb的Bean对象是单例 且 允许自动解决循环依赖问题 且 该beanName正在创建(在整个工厂内)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//如果是单例饿汉式暴露的情况
if (earlySingletonExposure) {
//打印跟踪信息
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//添加 新的单例对象工厂 singletonFactories 来构建 指定的单例对象。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
···
- 注入 A 的依赖对象,如 B 的 Bean对象。
AbstractAutowireCapableBeanFactory # doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
···
try {
//【开始注入依赖对象】
//用来自 BeanDefinition的属性值填充instanceWrapper中的bean实例
populateBean(beanName, mbd, instanceWrapper);
//初始化给定的Bean实例,应用工厂回调以及init方法和BeanPostProcessors,
// @Autowire的属性通过BeanPostProcessor注入
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
···
- 由于 B 还有被实例化,所以又会从 1~3 的步骤开始,得到 B 对应的 实例对象。到了第4步,需要注入 A对象,但由于 A 对象处于正在实例化的状态,但A的对象已经实例化出来,所以调用getBean方法获取A对象时,会走下面代码:
AbstractBeanFactory # doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly)
...
// Eagerly check singleton cache for manually registered singletons.
// 译:认真检查单例缓存中是否有手动注册的单例。
// 获取beanName的单例对象,并允许创建早期引用。
// 其最终实现:DefaultSingletonBeanRegistry#getSingleton(beanName,true);
Object sharedInstance = getSingleton(beanName);
...
当sharedInstance不为null的时候,就会返回出去。所以直接来看 DefaultSingletonBeanRegistry # getSingleton(beanName) 具体实现
/**
* 获取beanName的单例对象,并允许创建早期引用
* @param beanName the name of the bean to look for - 要寻找的bean名
* @see #getSingleton(String, boolean)
*/
@Override
@Nullable
public Object getSingleton(String beanName) {
//获取beanName的单例对象,并允许创建早期引用
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例对象的高速缓存中获取beanName的单例对象
Object singletonObject = this.singletonObjects.get(beanName);
//如果单例对象没有找到,并且 baneName 是正在被创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//同步,以singletonObjects作为锁
synchronized (this.singletonObjects) {
//从早期单例对象的高速缓存中获取bean对象
singletonObject = this.earlySingletonObjects.get(beanName);
//如果获取不了bean的单例对象,且允许创建早期引用
if (singletonObject == null && allowEarlyReference) {
//从单例工厂的缓存中获取beanName的单例工厂对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果beanName的单例工厂对象找到了
if (singletonFactory != null) {
//从beanName的单例工厂对象中获取该beanName的单例对象
singletonObject = singletonFactory.getObject();
//下面的操作主要是为了防止beanName对应的对象重复构建
//添加beanName和其对应的beanName单例对象到 早期单例对象高速缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//从单例对象工厂缓存中移除beanName的单例对象工厂
this.singletonFactories.remove(beanName);
}
}
}
}
//返回beanName对应的单例对象
return singletonObject;
}
由于 A 对应的 ObjectFactory 对象已经将 添加到了 singletonFactories 中,调用 ObjectFactory#.getObject() 其实就是回调 第 3 步的 getEarlyBeanReference 方法:
/**
* <p>该方法由 ObjectFactory实例的 getObject 方法 调用</p>
* Obtain a reference for early access to the specified bean,
* typically for the purpose of resolving a circular reference.
* <p>获取对 指定Bean 的 早期访问引用,通常用于解决循环引用</p>
* @param beanName the name of the bean (for error handling purposes) -- bean的名称(用于处理错误)
* @param mbd the merged bean definition for the bean -- 合并后的BeanDefinition对象
* @param bean the raw bean instance -- 原始Bean实例
* @return the object to expose as bean reference -- 要公开为bean引用的对象
*/
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
//默认最终公开的对象是bean
Object exposedObject = bean;
//mbd的systheic属性:设置此bean定义是否是"synthetic",一般是指只有AOP相关的prointCut配置或者Advice配置才会将 synthetic设置为true
//如果 mdb不是syntheic 且 此工厂拥有InstiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//遍历 工厂内的所有后处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果 bp 是 SmartInstantiationAwareBeanPostProcessor实例
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
//让exposedObject经过每个SmartInstantiationAwareBeanPostProcessor的包装
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
//返回最终经过层次包装后的对象
return exposedObject;
}
然后将 getEarlyBeanReference 的返回结果作为A的实例对象添加到 earlySingletonObjects 中,并删除 singletonFactories 的记录。
- 此时 B 就能得到 A 的实例对象,然后注入到 B 的实例对象中,最后添加到 singletonObjects 中,并删除 singletonsCurrentlyInCreation 中B的记录,表明B的Bean对象已经构建完成。
DefaultSingletonBeanRegistry # getSingleton(String beanName, ObjectFactory<?> singletonFactory)
...
//创建单例后的回调,默认实现将单例标记为不在创建中
afterSingletonCreation(beanName);
}
//生成了新的单例对象
if (newSingleton) {
//将beanName和singletonObject的映射关系添加到该工厂的单例缓存中:
addSingleton(beanName, singletonObject);
}
...
- 回到 A 的 构建步骤,此时由于B的Bean对象已经创建完成,A就可以正常注入B的Bean对象,最后
添加到 singletonObjects 中,并删除 singletonsCurrentlyInCreation 中 A 的记录 以及 earlySingletonObjects 中A的记录,表明B的Bean对象已经构建完成。
可能会有的疑问
- earlySingletonObjects 的作用
因为 Spring 需要保证每个单例对象只能实例化一次,singletonFactories 是用于实例对象的。如果有还有一种情况 B 还依赖于 C,C还依赖于 A 的情况,如果没有 earlySingletonObjects 会导致 A 的重复实例化。 - 为什么不将 singletonFactories 的实例化出来的对象直接放到 singletonObjects 中呢?
因为 singletonFactories 实例化出来的对象还处于 创建中,还有很多的初始化操作未完成,而 singletonObjects 保存着的是最终的实例对象,是完全已经初始化好的对象,是最终的Bean对象。 - B 对象 获取到是 从 earlySingletonObjects 拿到 A 的对象,但是A此时还没有初始化完成,此时B 对象所得到的A对象会不会是不完整的呢?
不会,因为A的对象即使还没有初始化完就已经注入B对象,但操作的对象都是同一个对象,所以B所注入的A对象最终再A初始化完以后也是一个完整的A对象。即使在注入时被 SmartInstantiationAwareBeanPostProcessor 封装成了另一个对象,但因为只要另一个对象有A对象的引用,所得到A对象也是完整的。