我怎样才能在spring中解决循环依赖。当我们有一个类A依赖于类B而类B依赖于C时所以如何使用spring解决这些问题(基于注释)
答案 0 :(得分:2)
欢迎o SO。您应该提供PasswordTextBox.wrap(element)
,让我告诉您:
我的问题是假设B级注入A级......
<强> BeanA 强>
package test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BeanA {
@Autowired
BeanB b;
}
......而A类是在C级注入的......
package test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BeanC {
@Autowired
BeanA a;
}
而B就像
一样简单<强> BeanB 强>
package test;
import org.springframework.stereotype.Component;
@Component
public class BeanB {
}
这是我的测试:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RefTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml");
BeanC c = ac.getBean(BeanC.class);
System.out.println("is c null? " + (c == null));
System.out.println("is c.a null? " + (c.a == null));
System.out.println("is c.a.b null? " + (c.a.b == null));
}
}
我的 spring.xml 几乎为空(只有component-scan
):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="test" />
</beans>
结果是:
is c null? false
is c.a null? false
is c.a.b null? false
通常,如果注入不起作用,那是因为bean不是使用Spring创建的,而是使用new
运算符...
如果您使用不同的详细信息,请使用其他详细信息更新您的问题。
顺便说一句:我同意Ian Mc的说法,这不是循环依赖答案 1 :(得分:2)
尝试在构造函数中使用@Lazy注释,如下所示:
@Component
public class C {
private final A a;
@Autowired
public C(@Lazy final A a) {
this.a = a;
}
}
这使得A bean只在实际需要时初始化,而不是在应用程序启动时才初始化。
答案 2 :(得分:1)
首先让我声称循环依赖是坏的。不管你是否使用Spring。你应该重构你的代码,以便摆脱它们。
现在问题的解决方案:据我所知,只有在使用构造函数注入时,Spring才会无法处理循环依赖。所以,当你让spring通过property-或setter-injection注入这种依赖时,它应该可以工作。
答案 3 :(得分:1)
Rajeev,你所解释的不是循环依赖。您必须创建A,B和C作为Spring Beans,并让Spring管理相关的依赖项。
要清楚,循环依赖是A依赖于B,B依赖于C,但C依赖于A.那么在这种情况下首先要创建什么?您无法创建A,因为尚未创建B.您无法创建B,因为尚未创建C.并且您无法创建C,因为尚未创建A.所以春天停止了。
在你的情况下:A取决于B,B取决于C.那么现在呢? Spring说:我先创建C语言。然后我将创建B,最后我将创建A。
这是可能的,因为Spring将首先创建所有bean定义。然后,当创建bean时,Spring会理解连接,并以正确的顺序构建bean以解决依赖关系。
我创建了一个小型项目,模拟您的状况,以及您如何描述问题,以及稍后您在评论中如何回应。从来没有问题! Spring可以毫无问题地管理您描述的两种情况。我实现了InitialingBean来挂钩创建,以显示创建bean的顺序。
@Component
public class A implements InitializingBean {
@Autowired
private B b;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "My name is "+name+"; b name is "+b.getName();
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Creating A");
System.out.println("B name="+b.getName());
}
}
@Component
public class B implements InitializingBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "B [name=" + name + "]";
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Creating b");
}
}
@Component
public class C implements InitializingBean {
@Autowired
private A a;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "My name is "+name+"; a name is "+a.getName();
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Creating c");
System.out.println("A name="+a.getName());
}
}