春天。使用java配置解决循环依赖关系,无需@Autowired

2022-09-04 02:23:37

我有循环依赖和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
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配置中的循环依赖关系?


答案 1

您希望获得的行为如下

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;
}

答案 2

使用 和 的另一种方法是使用此模式:@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;
    }
}

这消除了对单独 -类的需求。此外,如果类存在于同一包中,则 -方法可能受包保护,以尽可能减少作用域。@ConfigurationsetB


推荐