我有循环依赖和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配置中的循环依赖?
答案 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和类本身中。但由于循环依赖很少见,我们可以负担得起黑客。