IOC指spring来创建对象实例,而不是Java代码中来做。
DI指spring根据对象的关系来注入相互之间的关系。
DI会引起相互引用的问题,即两个对象相互引用、相互依赖,类似于死锁的问题导致系统无法完成实例化。
报错如下:
1
2
3
4
5
6
7
|
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?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:347)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 61 more
|
解决办法是,不适用构造器注入,使用属性注入方式即可。其原理是属性注入方式是,先创建对象再去给对象的属性赋值。
代码如下:
xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<?
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
=
"myBoss1"
class
=
"beans.Boss"
>
<
property
name
=
"age"
value
=
"10"
/>
<
property
name
=
"male"
value
=
"false"
/>
<
property
name
=
"name"
value
=
"zhouhui"
/>
<!-- 引用car实例 -->
<
property
name
=
"car"
ref
=
"myCar1"
/>
</
bean
>
<
bean
id
=
"myCar1"
class
=
"beans.Car"
>
<
property
name
=
"brand"
value
=
"audi"
/>
<
property
name
=
"price"
value
=
"10"
/>
<!-- 引用boss对象 -->
<
property
name
=
"boss"
ref
=
"myBoss1"
/>
</
bean
>
<!-- 通过构造器注入方式的相互引用 -->
<
bean
id
=
"myBoss2"
class
=
"beans.Boss"
>
<
constructor-arg
name
=
"age"
value
=
"10"
/>
<
constructor-arg
name
=
"isMale"
value
=
"true"
/>
<
constructor-arg
name
=
"name"
value
=
"zhang"
/>
<!-- 引用car实例 -->
<
constructor-arg
name
=
"car"
ref
=
"myCar2"
/>
</
bean
>
<
bean
id
=
"myCar2"
class
=
"beans.Car"
>
<
constructor-arg
name
=
"brand"
value
=
"benz"
/>
<
constructor-arg
name
=
"price"
value
=
"100"
/>
<!-- 引用boss对象 -->
<
constructor-arg
name
=
"boss"
ref
=
"myBoss2"
/>
</
bean
>
</
beans
>
|
java代码:
1
2
3
4
5
6
7
8
9
|
@Test
public
void
testLoop(){
System.out.println(
"===========testLoop======================"
);
System.out.println(myCar1);
System.out.println(myBoss1);
System.out.println(myBoss2);
System.out.println(myCar2);
System.out.println(
"===========testLoop======================"
);
}
|
其中 myCar1 myBoss1是能正常执行的,加上myBoss2 myCar2之后就会报错。
需要特别注意的是,如果bean都是单例的,spring容易会缓存实例,属性注入的相互引用没有问题。不过如果是多例的bean,相互引用及时是属性注入方式,还是会报错。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!-- 通过属性注入方式的相互引用 -->
<
bean
id
=
"myBoss3"
class
=
"beans.Boss"
scope
=
"prototype"
>
<
property
name
=
"age"
value
=
"10"
/>
<
property
name
=
"male"
value
=
"false"
/>
<
property
name
=
"name"
value
=
"zhouhui"
/>
<!-- 引用car实例 -->
<
property
name
=
"car"
ref
=
"myCar3"
/>
</
bean
>
<
bean
id
=
"myCar3"
class
=
"beans.Car"
scope
=
"prototype"
>
<
property
name
=
"brand"
value
=
"audi"
/>
<
property
name
=
"price"
value
=
"10"
/>
<!-- 引用boss对象 -->
<
property
name
=
"boss"
ref
=
"myBoss3"
/>
</
bean
>
|
scope="prototype" 意思是 每次请求都会创建一个实例对象。两者的区别是:有状态的bean都使用Prototype作用域,无状态的一般都使用singleton单例作用域。
对于“prototype”作用域Bean,Spring容器无法完成依赖注入,因为“prototype”作用域的Bean,Spring容
器不进行缓存,因此无法提前暴露一个创建中的Bean。
本文转自 斯然在天边 51CTO博客,原文链接:http://blog.51cto.com/13172906/1955383,如需转载请自行联系原作者