Java 如何解决Spring中的循环依赖关系

Java 如何解决Spring中的循环依赖关系,java,spring,Java,Spring,如何解决spring中的循环依赖关系。当我们有一个类a依赖于类B,而类B依赖于C时,那么如何使用spring解决java(基于注释的)中的这些问题呢 我的问题是假设B类被注入到A类中 BeanA package test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class

如何解决spring中的循环依赖关系。当我们有一个类a依赖于类B,而类B依赖于C时,那么如何使用spring解决java(基于注释的)中的这些问题呢


我的问题是假设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类中

而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几乎为空(只有
组件扫描
存在):


结果是:

c是否为空?假的
c.a是空的吗?假的
c.a.b是否为空?假的
通常,若注入不起作用,这是因为bean不是使用Spring创建的,而是使用了
new
操作符

如果您以不同方式使用问题,请使用其他详细信息更新您的问题


顺便说一句:我同意Ian Mc的观点,这不是循环依赖。首先让我声明循环依赖是不好的。不管你是否使用弹簧。你应该重构你的代码来摆脱它们

现在,问题的解决方案是:据我所知,只有在使用构造函数注入时,Spring才能处理循环依赖关系。因此,当您让spring通过属性或setter注入来注入此依赖项时,它应该可以工作。

尝试在构造函数中使用注释,如下所示:

@Component
public class C {
    private final A a;

    @Autowired
    public C(@Lazy final A a) {
        this.a = a;
    }
}

这使得您的A bean只有在实际需要时才初始化,而不是在应用程序启动时,当它还没有准备好时才初始化。

Rajeev,您所解释的不是循环依赖关系。您必须创建A、B和C作为springbean,并让Spring管理相关的依赖项

需要明确的是,循环依赖是a依赖于B,B依赖于C,但C依赖于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());
}
}

将C定义为bean。。然后在B上自动连接(任何形式)C。。然后在A.上自动连线B。。当然,将B和A定义为bean,我不知道这是如何循环的?A依赖于B,B依赖于C是很自然的。请进一步解释,或者发布spring给出的错误。我的问题是,假设B类在A类中被注入,而A类在C类中被注入,那么A类如何没有被初始化就会产生问题。我希望使用initializingbean的解决方案是在PropertieSet()之后重写其方法的正确选项。@Rajeev请在问题中直接澄清,不要为此目的使用注释。通过Setter注入,Spring上可能存在循环依赖,您可以在该链接中看到
@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());
}
}