使用 Spring 3.X.X 我有 2 个用 @Primary 注释的服务,我创建了另一个配置类,我想在其中使用其中一个服务的“定制”版本。
出于某种原因,我在调试配置类时忽略了我看到它获得了正确的依赖项,但是当我想使用它时它设置了错误的依赖项。
我觉得用代码更容易解释,这里是一个例子:
接口(interface)富:
public interface Foo {
String getMessage();
}
硬编码默认消息的主要实现:
@Primary
@Service("FooImpl")
public class FooImpl implements Foo {
private String message = "fooDefaultMessage";
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
栏界面:
public interface Bar {
void doBar();
}
栏默认实现:
@Primary
@Service("BarImpl")
public class BarImpl implements Bar {
private Foo foo;
@Override
public void doBar() {
System.out.println(foo.getMessage());
}
public Foo getFoo() {
return foo;
}
@Autowired
public void setFoo(Foo foo) {
this.foo = foo;
}
}
到目前为止一切顺利,如果我想注入(inject)一个 Bar,我会得到预期的一切。事情是我有一个配置如下:
@Configuration
public class BeanConfiguration {
@Bean
@Qualifier("readOnlyFoo")
Foo readOnlyFoo() {
FooImpl foo = new FooImpl();
foo.setMessage("a read only message");
return foo;
}
@Bean
@Qualifier("readOnlyBar")
Bar readOnlyBar() {
BarImpl bar = new BarImpl();
bar.setFoo(readOnlyFoo());
return bar;
}
}
当我想注入(inject)一个 readOnlyBar 时,我得到的是默认的 Foo 而不是此处设置的 Foo。
private Bar readOnlyBar;
@Autowired
@Qualifier("readOnlyBar")
public void setReadOnlyBar(Bar readOnlyBar) {
this.readOnlyBar = readOnlyBar;
}
...
readOnlyBar.doBar();
拥有带有“fooDefaultMessage”的 Foo bean。这是为什么?我如何确保 Spring 使用我在 @Configuration 上设置的 Bean?
提前致谢
编辑:请注意,如果您没有调用 @Configuration 类中的 readOnly() 方法,而是传递了一个 @Qualified 参数,则会发生同样的情况。即:
@Configuration
public class BeanConfiguration {
@Bean
@Qualifier("readOnlyFoo")
Foo readOnlyFoo() {
FooImpl foo = new FooImpl();
foo.setMessage("a read only message");
return foo;
}
@Bean
@Qualifier("readOnlyBar")
Bar readOnlyBar(@Qualifier("readOnlyFoo") Foo readOnlyFoo) {
BarImpl bar = new BarImpl();
bar.setFoo(readOnlyFoo);
return bar;
}
}
如果我改为尝试使用 Constructor 依赖注入(inject),一切都会按我想要/预期的方式工作,但不幸的是我不能使用它。
最佳答案
正如@yaswanth 在他的回答中指出的那样,问题是 foo
属性被创建 bean 后发生的属性注入(inject)覆盖。
解决这个问题的一种方法是对 BarImpl
使用构造函数注入(inject)而不是属性注入(inject)。这将使您的代码看起来像...
@Primary @Service("BarImpl")
class BarImpl implements Bar
{
private Foo foo;
@Autowired
public BarImpl(Foo foo) {
this.foo = foo;
}
}
你的配置是...
@Configuration
class BeanConfiguration
{
@Bean @Qualifier("readOnlyFoo")
Foo readOnlyFoo() {
FooImpl foo = new FooImpl();
foo.setMessage("a read only message");
return foo;
}
@Bean @Qualifier("readOnlyBar")
Bar readOnlyBar(@Qualifier("readOnlyFoo") Foo readOnlyFoo) {
return new BarImpl(readOnlyFoo);
}
}
作为旁路;你还应该确保在你的工厂方法中使用依赖注入(inject)而不是显式调用工厂方法,否则你最终会得到你的 bean 的多个实例......
祝你 future 工作顺利!
关于java - Spring 覆盖 bean 配置设置其 "Primary"一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47098752/