假设我有这堂课
class Foo implements IFoo { Foo() {} }
class Fooz implements IFoo { Fooz() {}}
class Foobar implement IFoobar {
@Autowired
Foobar (Foo foo) {}
}
class Foobarz implement IFoobar {
@Autowired
Foobarz (Bar bar) {}
}
在简单的情况下,我可以解决我的问题:
class Bar {
@Autowired
Bar (IFoo foo) {
this.foo = foo;
}
}
但是,如果我想能够根据我的配置文件选择IFoo和IFoobar实例,我需要这样做:
@Configuration
class Configuration {
@Bean
foo () {
return this.isZ() ? new Fooz() : new Foo ();
}
@Bean
foobar () {
return this.isZ() ? new Foobarz(/* ??????? */) : new Foobar (/* ??????? */);
}
}
如您所见,我无法实例化Foobar,因为我需要另一个bean。我知道有ApplicationContext.getBean,但是我不确定在调用Configuration
时,它是否会在我的foobar()
类中初始化。
我也不想调用this.foo()
,因为那样会创建该对象的另一个引用,并且我不确定执行和初始化的顺序
答案 0 :(得分:1)
在您的情况下,以下方法可以解决问题
@Configuration
class Configuration {
@Bean
IFoo foo() {
return this.isZ() ? new Fooz() : new Foo ();
}
@Bean
IFoobar foobar(IFoo foo) { // IFoo bean declared above will be injected here by Spring
return this.isZ() ? new Foobarz(foo) : new Foobar(foo);
}
}
已更新
但是,更优雅的方法是在类中放置@Service
或@Component
注释(@Bean
声明应从配置中删除) ...
package com.foobarpkg.maybeanotherpkg;
@Service
class Foobar implement IFoobar {
@Autowired
Foobar (IFoo foo) { // not that interface should be used here instead of concrete class (Foo/Fooz)
}
}
...并让Spring知道其软件包位于
@Configuration
@ComponentScan(basePackages = {"com.foobarpkg"})
class Configuration {
@Bean
IFoo foo() {
return this.isZ() ? new Fooz() : new Foo ();
}
// foobar bean is no longer declared here
}