voi*_*oid 8 java spring spring-bean
使用Spring 3.XX我有2个使用@Primary注释的服务,我创建了另一个配置类,我想使用其中一个服务的"自定义"版本.
出于某种原因,我在调试配置类时忽略了我看到它获得了正确的依赖关系,但是当我想使用它时,它设置了错误的依赖关系.
我发现使用代码更容易解释,这是一个例子:
界面Foo:
public interface Foo {
String getMessage();
}
Run Code Online (Sandbox Code Playgroud)
使用硬编码的默认消息的主要实现:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
栏界面:
public interface Bar {
void doBar();
}
Run Code Online (Sandbox Code Playgroud)
栏默认实施:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利,如果我想要注入一个酒吧,我会按预期得到一切.事情是我有一个配置如下:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
当我想注入一个readOnlyBar时,我得到了默认的Foo而不是这里设置的那个.
private Bar readOnlyBar;
@Autowired
@Qualifier("readOnlyBar")
public void setReadOnlyBar(Bar readOnlyBar) {
this.readOnlyBar = readOnlyBar;
}
...
readOnlyBar.doBar();
Run Code Online (Sandbox Code Playgroud)
Foo bean的"fooDefaultMessage".这是为什么?如何确保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;
}
}
Run Code Online (Sandbox Code Playgroud)
相反,如果我尝试使用构造函数依赖注入,一切都按照我想要/期望的方式工作但不幸的是我无法使用它.
您不能像您那样使用@Autowired
实例变量并在方法中设置它。@Bean
spring 生命周期的一部分是这样的
扫描 Bean 定义 => 创建 Bean 实例 => 调用后处理器 => .....
在你的例子中,
@Bean
@Qualifier("readOnlyBar")
Bar readOnlyBar() {
BarImpl bar = new BarImpl();
bar.setFoo(readOnlyFoo());
return bar;
}
Run Code Online (Sandbox Code Playgroud)
readOnlyBar
bean 被创建,并且因为readOnlyFoo()
是从该方法中调用的,所以readOnlyFoo
bean 也被实例化。到目前为止,它的实例变量已经存在readOnlyBar
。readOnlyFoo
一旦 bean 被实例化,AutowiredAnnotationBeanPostProcessor
就会调用 来扫描 bean 的类(BarImpl
在本例中)以查找@Autowired
实例变量或方法上的任何注释。@Autowired
它找到它们并尝试使用字段注入或 setter 注入(无论注释存在的位置)将 bean 注入到相应的变量中。在这种情况下,由于我们有@Autowired
setter并且没有指定注释@Qualifier
,所以spring注入的@Primary
bean就是defaultFooMessage
bean。
AFAIK,在 spring 中没有直接的方法来配置@Bean
优先于自动装配的方法。
使用方法实例化所有 bean@Bean
将解决该问题。
归档时间: |
|
查看次数: |
1466 次 |
最近记录: |