循環(huán)依賴是指多個類循環(huán)嵌套引用胎挎,如:A類引用B類泵额,B類引用C類挟冠,C類引用A類。
第一種:構(gòu)造器參數(shù)循環(huán)依賴
Spring容器會將每一個正在創(chuàng)建的Bean標(biāo)識放在一個“當(dāng)前創(chuàng)建Bean池中巩梢,Bean標(biāo)識符在創(chuàng)建過程中將一直保持在這個池中创泄。
如果在創(chuàng)建Bean過程中發(fā)現(xiàn)自己已經(jīng)在“當(dāng)前創(chuàng)建Bean池”里時將拋出BeanCurrentlyInCreationException異常表示循環(huán)依賴;而創(chuàng)建完成的Bean將從“當(dāng)前創(chuàng)建Bean池”中清除掉且改。
看如下實例:
看配置文件的構(gòu)造器參數(shù)配置:
<bean id="a" class="com.soecode.lyf.test.StudentA" >
? ?<constructor-arg index="0" ref="b"/>
</bean>
<bean id="b" class="com.soecode.lyf.test.StudentB" >
?????<constructor-arg index="0" ref="c" >
</bean>
<bean id="c" class="com.soecode.lyf.test.StudentC" >
?????<constructor-arg index="0" ref="a" >
</bean>
這三個就是StudentA類中有StudentB類验烧,StudentB類中有StudentC類,StudentC類中有StudentA類又跛。
第二種:setter方式單列碍拆,默認(rèn)方式
看如下實例:
setter 方式注入 scope默認(rèn)為singleton
<bean id="a" class="com.soecode.lyf.test.StudentA" >
????<property name="studentB" ref="b">
</bean>
<bean id="b" class="com.soecode.lyf.test.StudentB" >
????<property name="studentC" ref="c" >
</bean>
<bean id="c" class="com.soecode.lyf.test.StudentC" >
????<property name="studentA" ref="a" >
</bean>
執(zhí)行結(jié)果:
為什么用setter方式就不報錯了呢?
/**?Cache?of?singleton?factories:?bean?name?-->?ObjectFactory(單例的工廠Bean緩存集合)?*/慨蓝、privatefinalMap?singletonFactories?=newHashMap(16);
1.創(chuàng)建StudentA a單列時感混,首先無參構(gòu)造創(chuàng)建,并暴露到singletonFactories中礼烈,并將a 標(biāo)志符放到當(dāng)前正在創(chuàng)建Bean池, 然后進(jìn)行setter出入StudentB b弧满。
2.創(chuàng)建StudentB b單列時,首先無參構(gòu)造創(chuàng)建此熬,并暴露到singletonFactories中庭呜,并將b 標(biāo)志符放到當(dāng)前正在創(chuàng)建Bean池, 然后進(jìn)行setter出入StudentC c。
3.創(chuàng)建StudentC c單列時犀忱,首先無參構(gòu)造創(chuàng)建募谎,并暴露到singletonFactories中,并將b 標(biāo)志符放到當(dāng)前正在創(chuàng)建Bean池, 然后進(jìn)行setter出入StudentA a阴汇。在注入 a 時数冬,由于提前暴露在singletonFactories集合中了,利用它就可以取到 a 正在創(chuàng)建的Bean對象搀庶。
4. 最后依賴注入StudentB拐纱、StudentA
第三種:setter方式 原型注入
看配置文件:
scope=”property“ 意思是每一次請求都會創(chuàng)建一個實例對象铜异。
兩者的區(qū)別是:有狀態(tài)的bean都使用property作用域,無狀態(tài)的一般都使用singleton單列作用域秸架。
看運行之后的控制臺輸出:
總結(jié):為什么setter方式 singleton單列會成功揍庄,而setter方式 property原型會報BeanCurrentlyInCreationException?
因為單列的時候咕宿,會將bean放在緩存中币绩,可以提前暴露此接口。
而property原型不會放入緩存中府阀,無法提前暴露缆镣。