spring bean有两种 注入方式
对于构造器注入的循环依赖,Spring处理不了,会直接抛出BeanCurrentlylnCreationException异常。
对于属性注入的循环依赖(单例模式下),是通过三级缓存处理来循环依赖的。
singletonObjects 一级缓存 主要存放Spring完整生命周期的单例bean
earlySingletonObjects二级缓存 主要存放完成实例化未初始化的单例对象map,bean name -->
singletonFactories : 单例对象工厂map,bean name --> ObjectFactory,单例对象实例化完成之后会加入singletonFactories
spring 容器在获取bean的时候首先从一级缓存总获取,获取不到,到二级缓存获取,如果获取不到到三级缓存获取,如果从三级缓存获取到了就会从三级缓存中删除缓存,然后将从三级缓存获取的半成品bean放到二级缓存
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
//若一级缓存中没有,且当前bean正在创建中
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) {
/**
* 从对象工厂中获取到一个半成品bean
*/
singletonObject = singletonFactory.getObject();
//放入到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
在获取bean的时候,添加三级缓存
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory