博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring中的相互引用问题
阅读量:7044 次
发布时间:2019-06-28

本文共 3658 字,大约阅读时间需要 12 分钟。

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

你可能感兴趣的文章
查看gcc/g++默认include路径
查看>>
本期最新 9 篇论文,每一篇都想推荐给你 | PaperDaily #14
查看>>
CentOS7修改JAVA_HOME的环境变量
查看>>
背水一战 Windows 10 (33) - 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch
查看>>
PgSQL · 特性分析 · MVCC机制浅析
查看>>
比利时“Belgacom”网络系统被攻击
查看>>
WEB SSH之Shellinabox
查看>>
Java工作利器之常用工具类(四)——Json工具类,使用正则支持xml与json互转
查看>>
符号执行:利用Angr进行简单CTF逆向分析
查看>>
码农福音!CASIL开发代码移植系统,CTRL+C/V快速编程不再是梦想
查看>>
DevOps的四种核心能力
查看>>
【LeetCode从零单排】No22.Generate Parentheses
查看>>
GIT中文乱码问题解决方案
查看>>
ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider
查看>>
明全策:MACD平滑异同平均线实战运用!
查看>>
【翻译】PHP7——新特性
查看>>
Vectors For All (almost)
查看>>
zabbix3.2监控Windows网卡流量
查看>>
《VMware Virtual SAN权威指南》一1.7 小结
查看>>
用友网络并购秉钧网络 加速布局企业互联网服务
查看>>