源码解读全文
循环依赖
发生原因
- 在
ABean赋值环节populateBean,需要BBean,通过getBeanNamesForType找到匹配到的BBean后,需要通过getBean获取,那么就需要创建BBean,而此时BBean,根据同样的步骤,获取AABean,产生了循环注入 - 由于
BBean中需要的是完整代理处理后的ABean,那么就需要提前对ABean进行代理处理,才能放入BBean中 - 而由于,
cglib中的代理对象包含一个普通对象,那么就可以保证引用不变的情况下,先将包装成代理对象的ABean注入BBean,解决完循环依赖后,再对ABean完成剩下的注入流程
解决循环依赖,回到
ABean的createBean的流程中时,此时赋值处理的仍然是ABean的普通对象,而这个普通对象此时也被注入到BBean中的ABean的代理对象所持有,那么也可以保证ABean中的普通对象,是完整的
前提准备
加入singletonsCurrentlyInCreation
getSingleton中beforeSingletonCreation(beanName);
- 其中会有
double-check
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
加入三级缓存
- 完成
instanceWrapper = createBeanInstance(beanName, mbd, args);,创建一个实例后,进行循环依赖解决的准备,支持循环依赖就会被放入三级缓存
// earlySingletonExposure 标志位
// 是单例 && 可以自动解决循环依赖 && 是在创建过程
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");
}
//加入三级缓存,采用`lambda`表达式,加入的工厂类
//最终通过`getEarlyBeanReference`,获取到三级缓存的对象,也会被后置处理增强
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
addSingletonFactory,加入的是singletonFactory
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//工厂类,添加到三级缓存
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
ObjectFactory工厂接口
public interface ObjectFactory<T> {
T getObject() throws BeansException;
}
getEarlyBeanReference
- 过程中
wrapIfNecessary(bean, beanName, cacheKey);,生成代理对象
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
避免重复生成代理对象
getEarlyBeanReference,将Bean记录在earlyProxyReferences
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
//生成代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
三级缓存的解决
- 一级也能解决,但是三级更有层次感
- 用标识符来表示
>表示刚刚实例化;@表示完整对象
singletonObjects一级缓存,单例池earlySingletonObjects二级缓存,保存提前生成的代理对象,便于后边比较,防止重复生成,保证单例singletonFactories三级缓存,以ObjectFactory的形式,保存早期实例化的Bean,以直接获取代理对象earlyProxyReferences保存已经进行代理处理过的Bean防止重复处理singletonsCurrentlyInCreation开始创建前保存,判定循环依赖的标志
细节
- 在
getBean过程中,会先检查缓存,并允许早期引用,从其他缓存中获取
发生循环依赖时,三级缓存中是存在的,因此,就从三级缓存的工厂类中,注入早期的引用
Bean,此时这个Bean还没有完成赋值和初始化
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 检查单例池缓存,一级缓存是否有当前对象
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null &&
// 是否正在创建,那么就发生了循环依赖
isSingletonCurrentlyInCreation(beanName)) {
// 从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
//double-check,一级缓存
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//二级缓存
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//三级缓存
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//调用`getObject`
singletonObject = singletonFactory.getObject();
//生成的代理对象放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
后续处理
- 解决以上方案带来的影响
提早生成了代理对象
避免重复代理处理
- 回到
createBean的流程中的exposedObject = initializeBean(beanName, exposedObject, mbd);,调用后置处理器 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);,如果需要代理处理时,调用AbstractAutoProxyCreator.postProcessAfterInitialization,过程中检查earlyProxyReferences
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
返回Bean的比较
- 如果发生循环依赖,引起循环依赖的
Bean存在于二级缓存中
if (earlySingletonExposure) {
//能从二级缓存中获取到,传入 false 只能从二级缓存中获取
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//exposedObject 该对象接受了赋值/后置处理器/初始化的处理
//如果在处理过程中,导致该对象引用改变,被包装成代理对象,那么此时就不符合原则
//没有发生变化,那么直接返回二级缓存中的代理对象
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// ...
}
}
}