什么是循環(huán)依賴
簡單的說就是A依賴B,B依賴C,C依賴A這樣就構(gòu)成了循環(huán)依賴

循環(huán)依賴分為構(gòu)造器依賴和屬性依賴,眾所周知的是Spring能夠解決屬性的循環(huán)依賴(set注入)。下文將從源碼角度分析Spring是如何解決屬性的循環(huán)依賴。
如下配置會產(chǎn)生循環(huán)依賴
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.yao.bean.Person">
<property name="cat" ref="cat"></property>
</bean>
<bean id="cat" class="com.yao.bean.Cat">
<property name="person" ref="person"></property>
</bean>
</beans>
@Test
public void testAbc() throws IOException {
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
//獲取bean的時候就會涉及到循環(huán)依賴的處理
Person person = (Person) bf.getBean("person");
person.say();
}
我們跟進源碼可以看到如下代碼
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//修正名稱
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//從單例緩存中獲取bean,這里就涉及到spring的1,2,3級緩存,第一次獲取的時候sharedInstance 肯定為空
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 對于scope==prototype的,如果出現(xiàn)循環(huán)依賴,則直接拋異常,無法處理
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
......
if (!typeCheckOnly) {
//標記當(dāng)前bean正在創(chuàng)建,就是將當(dāng)前的beanName放到Set集合中,后面會作為其中一個判斷條件去判斷是否去從1或者2或者3級緩存中獲取bean
markBeanAsCreated(beanName);
}
try {
......
// Create bean instance.
//創(chuàng)建bean實力的邏輯,
if (mbd.isSingleton()) {
//獲取beanName的實力
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
......
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
......
return (T) bean;
查看public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)如下
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
//從一級緩存中獲取bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
...
try {
/**
* 這里singletonFactory.getObject()實際是上一步中的匿名內(nèi)部類的方法,即try中的語句塊
* sharedInstance = getSingleton(beanName, () -> {
* try {
* return createBean(beanName, mbd, args);
* }...)
*/
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
...
return singletonObject;
}
}
我們可以繼續(xù)返回上一步中繼續(xù)查看return createBean(beanName, mbd, args);邏輯
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
try {
//這里是真正創(chuàng)建bean的邏輯,真正處理的邏輯一般都是doXXXX,do開頭的
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
...
}
繼續(xù)查看doCreateBean()邏輯
這一步第一次將A放入了三級緩存,這個時候A實例化,但是未初始化。
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) {
//這里最終會使用jdk的類加載器去去實例化當(dāng)前bean,僅僅只是newInstance,
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
// ......
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//緩存單例用于接續(xù)循環(huán)依賴,
//(單例 && 允許循環(huán)依賴(此處是恒定值,但是可以利用別的BeanFactory實現(xiàn)去改寫這個值) && 當(dāng)前bean是否處于正在創(chuàng)建中)
//這里為true,進入if,
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");
}
//添加到三級緩存,但是這時候bean還未實例化,下次別的Bean依賴的時候在調(diào)用真正的邏輯(匿名內(nèi)部類)
//這里的匿名內(nèi)部類意思是: 提前將實例化的bean暴露出去,記住,僅僅是實例化,沒有初始化
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充屬性,這個時候發(fā)現(xiàn)屬性A類中的B屬性未實例化,則實例化B,實例化B之后,則把把B的屬性填充給A,這個時候填充
//的時候回從三級緩存中獲取Bean
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
//......
return exposedObject;
}
繼續(xù)查看填充屬性的邏輯AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//......
//這里去發(fā)現(xiàn)當(dāng)前bean需要填充的屬性,也就是需要依賴的對象屬性,這個時候如果pvc肯定不為空,繼續(xù)進入下面if語句
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//......
if (pvs != null) {
//將依賴的屬性賦值到當(dāng)前bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
查看applyPropertyValues
AbstractAutowireCapableBeanFactory.java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
//獲取需要填充的屬性名稱s
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
//循環(huán)去填充所有的屬性值
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
//依賴的屬性名稱
String propertyName = pv.getName();
//依賴的屬性值,第一次這個值的類型是 RuntimeBeanReference
Object originalValue = pv.getValue();
//解析屬性,里面的邏輯會進入RuntimeBeanReference判斷邏輯,進行屬性的解析
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
繼續(xù)查看valueResolver.resolveValueIfNecessary()
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
//上一步說的那個屬性值是RuntimeBeanReference,這里判斷一下為true,那就繼續(xù)解析屬性
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//繼續(xù)解析依賴的屬性。
return resolveReference(argName, ref);
}
//...
繼續(xù)查看resolveReference()方法可以看到準備在factory中解析依賴的bean
/**
* Resolve a reference to another bean in the factory.
* 在factory中解析對另一個bean的引用
*/
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
//...
}
else {
//這里會從factory中獲取引用的bean,第一次循環(huán)完畢。里面會重頭進入doGetBean()相關(guān)方法,然后一步步會獲取引用的bean.
bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
}
//...
return bean;
}
//...
}
至此在初始化A的時候(只是實例化為初始化)的過程中,發(fā)現(xiàn)需要依賴B,那么這個時候再去factory中去找B,接下來我們發(fā)現(xiàn)B走了同樣的流程,然后繼續(xù)初始化A,此時狀態(tài)如下:

程序?qū)嵗盟械腷ean之后,第二輪開始進行依賴bean的set值,我們會看到剛開頭的代碼
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//修正名稱
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//從單例緩存中獲取bean,這里就涉及到spring的1,2,3級緩存
Object sharedInstance = getSingleton(beanName);
//...
繼續(xù)查看getSingleton(beanName);
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//第二輪進入的時候isSingletonCurrentlyInCreation(beanName)為true,進入if,每一次第一次初始化的bean的時候,都會
//標識此bean正在創(chuàng)建中。
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//從二級緩存獲取,此時為null,allowEarlyReference默認一直true
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//從3級緩存獲取之前存儲的匿名內(nèi)部類
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//調(diào)用匿名內(nèi)部類的方法去執(zhí)行doCreateBean的創(chuàng)建
singletonObject = singletonFactory.getObject();
//將當(dāng)前實例化好,但是未初始化的A放入二級緩存
this.earlySingletonObjects.put(beanName, singletonObject);
//把當(dāng)前在三級緩存中存放的beanName移除掉
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
此時A,B在緩存中的狀態(tài)為:

接著會將這個A會暴露出去,讓B去完成A屬性的賦值,這個時候我們可以繼續(xù)查看初始化B的階段中給A屬性賦值的邏輯
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
//...
else {
//這個時候從factory中拿到了已經(jīng)實例化好的A
bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
}
return bean;
//...
}
賦值操作
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
//...
//循環(huán)去填充所有的屬性值
for (PropertyValue pv : original) {
//...
else {
//依賴的屬性名稱
String propertyName = pv.getName();
//依賴的屬性值,第一次這個值的類型是 RuntimeBeanReference
Object originalValue = pv.getValue();
//解析屬性,里面的邏輯會進入RuntimeBeanReference判斷邏輯,進行屬性的解析
//這個時候已經(jīng)解析到A屬性的Bean了,接下來就是把A 賦值給B bean即可完成B的實例化初始化
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
//...
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
//...
// Set our (possibly massaged) deep copy.
try {
//這里就是賦值操作
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
//...
}
一步步往下跟,我們可以看到如下代碼
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//將B放入一級緩存
this.singletonObjects.put(beanName, singletonObject);
//將B從三級緩存移除
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
此時A,B在1,2,3級緩存中的狀態(tài)如下:

此時B已經(jīng)完全的實例化并初始化完畢,可以正常的使用了。接下來就是繼續(xù)完成A中B屬性的賦值即可
剩下的邏輯我就不分析了。
A,B在1,2,3級緩存中的狀態(tài)變化如下:

至此spring如何解決循環(huán)依賴已經(jīng)分析完畢。但是我們需要思考以下幾個問題
只有一級緩存能否解決循環(huán)依賴?
只有一級是解決不了的,一級緩沖中到時候存放的bean你是不知道到底是不是初始化完畢的。