IOC指spring來建立對象執行個體,而不是Java代碼中來做。
DI指spring根據對象的關系來注入互相之間的關系。
DI會引起互相引用的問題,即兩個對象互相引用、互相依賴,類似于死鎖的問題導緻系統無法完成執行個體化。
報錯如下:
<code>Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'myBoss2': Requested bean is currently in creation: Is there an unresolvable circular reference?</code>
<code> </code><code>at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:347)</code>
<code> </code><code>at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)</code>
<code> </code><code>at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)</code>
<code> </code><code>at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)</code>
<code> </code><code>at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)</code>
<code> </code><code>... 61 more</code>
解決辦法是,不适用構造器注入,使用屬性注入方式即可。其原理是屬性注入方式是,先建立對象再去給對象的屬性指派。
代碼如下:
xml:
<code><?</code><code>xml</code> <code>version</code><code>=</code><code>"1.0"</code> <code>encoding</code><code>=</code><code>"UTF-8"</code><code>?></code>
<code><</code><code>beans</code> <code>xmlns</code><code>=</code><code>"http://www.springframework.org/schema/beans"</code>
<code> </code><code>xmlns:xsi</code><code>=</code><code>"http://www.w3.org/2001/XMLSchema-instance"</code>
<code> </code><code>xsi:schemaLocation</code><code>=</code><code>"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"</code><code>></code>
<code> </code><code><!-- 通過屬性注入方式的互相引用 --></code>
<code> </code><code><</code><code>bean</code> <code>id</code><code>=</code><code>"myBoss1"</code> <code>class</code><code>=</code><code>"beans.Boss"</code><code>></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"age"</code> <code>value</code><code>=</code><code>"10"</code><code>/></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"male"</code> <code>value</code><code>=</code><code>"false"</code><code>/></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"name"</code> <code>value</code><code>=</code><code>"zhouhui"</code><code>/></code>
<code> </code><code><!-- 引用car執行個體 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"car"</code> <code>ref</code><code>=</code><code>"myCar1"</code><code>/></code>
<code> </code><code></</code><code>bean</code><code>></code>
<code> </code><code><</code><code>bean</code> <code>id</code><code>=</code><code>"myCar1"</code> <code>class</code><code>=</code><code>"beans.Car"</code><code>></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"brand"</code> <code>value</code><code>=</code><code>"audi"</code><code>/></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"price"</code> <code>value</code><code>=</code><code>"10"</code><code>/></code>
<code> </code><code><!-- 引用boss對象 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"boss"</code> <code>ref</code><code>=</code><code>"myBoss1"</code><code>/></code>
<code> </code><code><!-- 通過構造器注入方式的互相引用 --></code>
<code> </code><code><</code><code>bean</code> <code>id</code><code>=</code><code>"myBoss2"</code> <code>class</code><code>=</code><code>"beans.Boss"</code><code>></code>
<code> </code><code><</code><code>constructor-arg</code> <code>name</code><code>=</code><code>"age"</code> <code>value</code><code>=</code><code>"10"</code><code>/></code>
<code> </code><code><</code><code>constructor-arg</code> <code>name</code><code>=</code><code>"isMale"</code> <code>value</code><code>=</code><code>"true"</code><code>/></code>
<code> </code><code><</code><code>constructor-arg</code> <code>name</code><code>=</code><code>"name"</code> <code>value</code><code>=</code><code>"zhang"</code><code>/></code>
<code> </code><code><</code><code>constructor-arg</code> <code>name</code><code>=</code><code>"car"</code> <code>ref</code><code>=</code><code>"myCar2"</code><code>/></code>
<code> </code><code><</code><code>bean</code> <code>id</code><code>=</code><code>"myCar2"</code> <code>class</code><code>=</code><code>"beans.Car"</code><code>></code>
<code> </code><code><</code><code>constructor-arg</code> <code>name</code><code>=</code><code>"brand"</code> <code>value</code><code>=</code><code>"benz"</code><code>/></code>
<code> </code><code><</code><code>constructor-arg</code> <code>name</code><code>=</code><code>"price"</code> <code>value</code><code>=</code><code>"100"</code><code>/></code>
<code> </code><code><</code><code>constructor-arg</code> <code>name</code><code>=</code><code>"boss"</code> <code>ref</code><code>=</code><code>"myBoss2"</code><code>/></code>
<code></</code><code>beans</code><code>></code>
java代碼:
<code>@Test</code>
<code>public</code> <code>void</code> <code>testLoop(){</code>
<code> </code><code>System.out.println(</code><code>"===========testLoop======================"</code><code>);</code>
<code> </code><code>System.out.println(myCar1);</code>
<code> </code><code>System.out.println(myBoss1);</code>
<code> </code><code>System.out.println(myBoss2);</code>
<code> </code><code>System.out.println(myCar2);</code>
<code>}</code>
其中 myCar1 myBoss1是能正常執行的,加上myBoss2 myCar2之後就會報錯。
需要特别注意的是,如果bean都是單例的,spring容易會緩存執行個體,屬性注入的互相引用沒有問題。不過如果是多例的bean,互相引用及時是屬性注入方式,還是會報錯。
<code><!-- 通過屬性注入方式的互相引用 --></code>
<code><</code><code>bean</code> <code>id</code><code>=</code><code>"myBoss3"</code> <code>class</code><code>=</code><code>"beans.Boss"</code> <code>scope</code><code>=</code><code>"prototype"</code><code>></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"age"</code> <code>value</code><code>=</code><code>"10"</code><code>/></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"male"</code> <code>value</code><code>=</code><code>"false"</code><code>/></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"name"</code> <code>value</code><code>=</code><code>"zhouhui"</code><code>/></code>
<code> </code><code><!-- 引用car執行個體 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"car"</code> <code>ref</code><code>=</code><code>"myCar3"</code><code>/></code>
<code></</code><code>bean</code><code>></code>
<code><</code><code>bean</code> <code>id</code><code>=</code><code>"myCar3"</code> <code>class</code><code>=</code><code>"beans.Car"</code> <code>scope</code><code>=</code><code>"prototype"</code><code>></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"brand"</code> <code>value</code><code>=</code><code>"audi"</code><code>/></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"price"</code> <code>value</code><code>=</code><code>"10"</code><code>/></code>
<code> </code><code><!-- 引用boss對象 --></code>
<code> </code><code><</code><code>property</code> <code>name</code><code>=</code><code>"boss"</code> <code>ref</code><code>=</code><code>"myBoss3"</code><code>/></code>
scope="prototype" 意思是 每次請求都會建立一個執行個體對象。兩者的差別是:有狀态的bean都使用Prototype作用域,無狀态的一般都使用singleton單例作用域。
對于“prototype”作用域Bean,Spring容器無法完成依賴注入,因為“prototype”作用域的Bean,Spring容
器不進行緩存,是以無法提前暴露一個建立中的Bean。
<b>本文轉自 斯然在天邊 51CTO部落格,原文連結:</b><b>http://blog.51cto.com/13172906/1955383</b><b>,如需轉載請自行聯系原作者</b>