此依赖无法解决,只能抛出异常表示循环依赖。因为使用构造器产生的循环依赖会造成一个环,比如创建A,A构造器需要B,那么创建B,B构造器又需要C,那么创建C,C构造器又需要A,从而导致死循环构造对象。
以两个对象构成的循环依赖为例进行分析。
Spring解决循环依赖使用了以下三个Map进行存储。两个set集合进行辅助处理。
/**用于存放BeanName和创建bean实例(instance)之间的关系 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 用于存放BeanName和 创建bean工厂 (FactoryBean)之间的关系 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 用于存放创建的原始bean的一个引,即使用工厂方法或构造方法创建出来的对象,一旦对象最终创建好,此引用信息将remove掉 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** 用于存放已加载的beanName */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** 用于存放正在创建的beanName */
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//1. bean的实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
synchronized (mbd.postProcessingLock) {
// 2. 满足循环依赖的条件是 :单例 && 允许循环依赖 && 当前bean正在创建
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//3.初始化完成前创建beanName与FactoryBean的缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 3. 属性注入
populateBean(beanName, mbd, instanceWrapper);
// 4. bean的初始化,调用initmethod
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
//1.判断bean是否加载,bean最后存放在singletonObjects缓存中。
Object singletonObject = this.singletonObjects.get(beanName);
//2. 有缓存直接返回,否则获取bean对象
if (singletonObject == null) {
//3. 将beanName添加进Set 集合 singletonsCurrentlyInCreation中
beforeSingletonCreation(beanName);
//4. 获取初始化bean,该bean是步骤一createBean中的对象
singletonObject = singletonFactory.getObject();
//5. 将beanName从Set集合 singletonsCurrentlyInCreation中移除
afterSingletonCreation(beanName);
//6. 加入缓存
addSingleton(beanName, singletonObject);
}
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//创建完bean之后只保存在singletonObjects中
this.singletonObjects.put(beanName, singletonObject);
//删除其他缓存singletonFactories,earlySingletonObjects
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
//保存加载完的beanName信息
this.registeredSingletons.add(beanName);
}
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//1.首先从缓存singletonObjects中取,如果不为空则直接返回。
//因为在bean的初始化之后bean的相关信息会加入到singletonObjects缓存中,earlySingletonObjects,singletonFactories为空
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//2.如果singletonObject 为空 && bean 正在创建,则尝试从earlySingletonObjects获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//3.earlySingletonObjects为空则从singletonFactories中获取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//4.将ObjectFactory 存放在earlySingletonObjects缓存中。
this.earlySingletonObjects.put(beanName, singletonObject);
//5.移除 singletonFactories 缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
.....省略无关代码....
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//1. earlySingletonReference 不为空则说明存在循环依赖,
//因为当创建A时要填充B时,此时A的singletonFactories有数据,然后转去创建B。
//当B创建完之后要填充A时去缓存getSingleton(beanName,true)拿A缓存这时删除了singletonFactories缓存,
//添加了earlySingletonObjects缓存,那么下次A填充完B之后执行这里时就有了缓存,
//则说明存在循环依赖
if (earlySingletonReference != null) {
//2. 如果相等则说明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) {
//3. 依赖检测
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//4. 不为空则说明当前bean创建后其依赖的bean还没有创建完,存在循环依赖,直接抛异常。
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
.....省略无关代码....
return exposedObject;
}
假如有两个对象A,B形成了循环依赖,在创建A时,也就是执行createBeanInstance之后,populateBean执行之前,这时通过addSingletonFactory()方法将ObjectFactory信息存放在了singletonFactories缓存中。接下来执行populateBean,检测到要填充的属性为对象beanB时则转向去创建B,当执行到B的populateBean时检测要填充属性对象A,而A已经存在于singletonFactories缓存中,所以B持有未填充属性的A对象,在A填充完了B之后继续填充A属性,因为B持有的A对象的地址与A对象地址一致,所以在A继续执行populateBean后B中持有的也是一致的。这就解决了循环依赖的问题。