Spring解决循环依赖的三级缓存

1,214 阅读2分钟

1 概述

Spring利用三级Bean缓存的方式解决Bean循环依赖的问题,三级缓存也就是DefaultSingletonBeanRegistry中的三个Map:

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
  • singletonObjects:一级缓存,存放完整的Bean;
  • earlySingletonObjects:二级缓存,存放早期Bean,即还没有设置属性的Bean;
  • singletonFactories:三级缓存,存放ObjectFactory对象,即Bean的生产工厂。

一个Bean的创建,经历了 singletonFactories -> earlySingletonObjects -> singletonObjects的三个过程。

处理时机:

  • 三级级和二级缓存,在创建bean的时候,即AbstractAutowireCapableBeanFactory.doCreateBean中设置;
  • 一级缓存,在获取Bean,即AbstractBeanFactory.doGetBean中设置。

2 三级缓存&二级缓存

AbstractAutowireCapableBeanFactory.doCreateBean:

// 放入三级缓存

// Bean是单例 && 允许循环依赖 && 当前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将一个ObjectFactory放入三级缓存,这个ObjectFactory通过getEarlyBeanReference方法获取对象。
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

//// 省略代码

// 放入二级缓存
if (earlySingletonExposure) {
	Object earlySingletonReference = getSingleton(beanName, false);
	//// 省略代码
}

2.1 getEarlyBeanReference

/* 遍历beanPostProcessor,如果是SmartInstantiationAwareBeanPostProcessor,则通过getEarlyBeanReference获取Object,否则使用原来实例化的Object。
 该方法返回早期对象,用于将来升级到二级缓存: 要么返回原Object,要么返回执行了AbstractAutoProxyCreator.getEarlyBeanReference获取加强后的Object代理对象。
*/
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
	Object exposedObject = bean;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
				exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
			}
		}
	}
	return exposedObject;
}

2.2 getSingleton

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
	    // 一级缓存中没有bean
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
			    // 二级缓存中没有早期对象
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
				    // 从前面的设置的ObjectFactory中,即getEarlyBeanReference方法中,获取早期对象
					singletonObject = singletonFactory.getObject();
					// 放入二级缓存
					this.earlySingletonObjects.put(beanName, singletonObject);
					// 清除三级缓存
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

3 一级缓存:

AbstractBeanFactory.doGetBean中:

// 依赖的beanName
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
	for (String dep : dependsOn) {
		if (isDependent(beanName, dep)) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
		}
		registerDependentBean(dep, beanName);
		// getBean调用前面的doCreate将依赖的早期Bean放入二级缓存
		getBean(dep);
	}
}

// 省略代码....

if (mbd.isSingleton()) {
    // 放入一级缓存
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			// Explicitly remove instance from singleton cache: It might have been put there
			// eagerly by the creation process, to allow for circular reference resolution.
			// Also remove any beans that received a temporary reference to the bean.
			destroySingleton(beanName);
			throw ex;
		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

3.1 getSingleton

getSingleton(String beanName, ObjectFactory<?> singletonFactory) 是AbstractBeanFactory的一个父类DefaultSingletonBeanRegistry中的方法,如过是新的bean,则执行addSingleton(beanName, singletonObject)将对象放入一级缓存中。

protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		this.singletonObjects.put(beanName, singletonObject);
		this.singletonFactories.remove(beanName);
		this.earlySingletonObjects.remove(beanName);
		this.registeredSingletons.add(beanName);
	}
}