首页 > 代码库 > spring中的相互引用问题
spring中的相互引用问题
IOC指spring来创建对象实例,而不是Java代码中来做。
DI指spring根据对象的关系来注入相互之间的关系。
DI会引起相互引用的问题,即两个对象相互引用、相互依赖,类似于死锁的问题导致系统无法完成实例化。
报错如下:
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:
<?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="http://www.mamicode.com/10"/> <property name="male" value="http://www.mamicode.com/false"/> <property name="name" value="http://www.mamicode.com/zhouhui"/> <!-- 引用car实例 --> <property name="car" ref="myCar1"/> </bean> <bean id="myCar1" class="beans.Car"> <property name="brand" value="http://www.mamicode.com/audi"/> <property name="price" value="http://www.mamicode.com/10"/> <!-- 引用boss对象 --> <property name="boss" ref="myBoss1"/> </bean> <!-- 通过构造器注入方式的相互引用 --> <bean id="myBoss2" class="beans.Boss"> <constructor-arg name="age" value="http://www.mamicode.com/10"/> <constructor-arg name="isMale" value="http://www.mamicode.com/true"/> <constructor-arg name="name" value="http://www.mamicode.com/zhang"/> <!-- 引用car实例 --> <constructor-arg name="car" ref="myCar2"/> </bean> <bean id="myCar2" class="beans.Car"> <constructor-arg name="brand" value="http://www.mamicode.com/benz"/> <constructor-arg name="price" value="http://www.mamicode.com/100"/> <!-- 引用boss对象 --> <constructor-arg name="boss" ref="myBoss2"/> </bean> </beans>
java代码:
@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,相互引用及时是属性注入方式,还是会报错。
<!-- 通过属性注入方式的相互引用 --> <bean id="myBoss3" class="beans.Boss" scope="prototype"> <property name="age" value="http://www.mamicode.com/10"/> <property name="male" value="http://www.mamicode.com/false"/> <property name="name" value="http://www.mamicode.com/zhouhui"/> <!-- 引用car实例 --> <property name="car" ref="myCar3"/> </bean> <bean id="myCar3" class="beans.Car" scope="prototype"> <property name="brand" value="http://www.mamicode.com/audi"/> <property name="price" value="http://www.mamicode.com/10"/> <!-- 引用boss对象 --> <property name="boss" ref="myBoss3"/> </bean>
scope="prototype" 意思是 每次请求都会创建一个实例对象。两者的区别是:有状态的bean都使用Prototype作用域,无状态的一般都使用singleton单例作用域。
对于“prototype”作用域Bean,Spring容器无法完成依赖注入,因为“prototype”作用域的Bean,Spring容
器不进行缓存,因此无法提前暴露一个创建中的Bean。
spring中的相互引用问题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。