spring中的相互引用问题

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,如需转载请自行联系原作者

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值