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

Art*_*nko 14 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我试过这个(我已经读过,使用@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Sot*_*lis 10

您想要获得的行为如下

A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
Run Code Online (Sandbox Code Playgroud)

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

@Bean
public B b(A a) {
    B b = new B();
    b.setA(a);
    a.setB(b);
    return b;
}
Run Code Online (Sandbox Code Playgroud)


was*_*ren 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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