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>