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