弹簧。使用java配置解决循环依赖关系,而不使用@Autowired

时间:2014-12-23 14:10:57

标签: java spring dependency-injection

我有循环依赖和java配置。虽然使用xml配置解析它非常容易,但我无法使用没有@Autowired的java配置解析它。豆:

public class A {
    private B b;

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }
}

public class B {
    private A a;

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }
}

我已经尝试了这个(我已经读过,使用@Bean注释Spring每次引用bean时都不会调用方法,但在这种情况下它实际上一直被调用):

@Configuration
public class Config {
    @Bean
    public A a() {
        A a = new A();
        a.setB(b());
        return a;
    }

    @Bean
    public B b() {
        B b = new B();
        b.setA(a());
        return b;
    }
}

这就是@Autowired的Configuration类字段:

@Configuration
public class Config {
    @Autowired
    A a;
    @Autowired
    B b;

    @Bean
    public A a() {
        A a = new A();
        a.setB(b);
        return a;
    }

    @Bean
    public B b() {
        B b = new B();
        b.setA(a);
        return b;
    }
}

此外,我已经使用@Lazy注释尝试了以上所有内容。没有帮助。但如果我用@Autowired注释A和B的setter,那么效果很好。但这不是我现在想要的。我做错了什么,有没有办法在不使用@Autowired的情况下解决java配置中的循环依赖?

3 个答案:

答案 0 :(得分:10)

您想要获得的行为如下

A a = new A();
B b = new B();
a.setB(b);
b.setA(a);

@Bean方法并不能解决这个问题。它们运行完成以提供bean实例。

您基本上必须部分创建其中一个实例,然后在您创建另一个实例时完成初始化。

@Configuration
class Config {
    @Bean
    public A a() {
        A a = new A();
        return a;
    }

    @Bean
    public B b() {
        B b = new B();
        A a = a();
        b.setA(a);
        a.setB(b);
        return b;
    }
}

@Bean
public B b(A a) {
    B b = new B();
    b.setA(a);
    a.setB(b);
    return b;
}

答案 1 :(得分:6)

使用@Autowired@Component的另一种方法是使用此模式:

@Component
class A {
    private B b;

    public B getB() {
        return b;
    }

    public void setB(final B b) {
        this.b = b;
    }
}


@Component
class B {
    private final A a;

    @Autowired
    public B(final A a) {
        this.a = a;
        a.setB(this);
    }

    public A getA() {
        return a;
    }
}

这消除了对单独的@Configuration - 类的需要。此外,如果类存在于同一个包中,setB - 方法可能会受到包保护,以尽可能地减少范围。

答案 2 :(得分:1)

我想为您的代码添加另一种可能的解决方案。而不是在配置中设置循环依赖:

@Configuration
public class Config {
    @Bean
    public A a() {
        A a = new A();
        a.setB(b());
        return a;
    }

    @Bean
    public B b() {
        B b = new B();
        b.setA(a());
        return b;
    }
}

你也可以让弹簧以@Autowired注释的力量完成工作。

@Configuration
public class Config {
    @Bean
    public A a() {
        A a = new A();
        return a;
    }

    @Bean
    public B b() {
        B b = new B();
        return b;
    }
}

public class A {
    private B b;

    @Autowired
    public setB(B b) { this.b = b; }
}

public class B {
    private A a;

    @Autowired
    public setA(A a) { this.a = a; }
}

当然,从清洁/可读/可理解的#34;开始,这是非常重要的。观点,因为现在您的配置混合在@Configuration和类本身中。但由于循环依赖很少见,我们可以负担得起黑客。