从这个Q / A:How to define a List bean in Spring?我知道我可以定义一个用List<Foo> fooList
bean实例填充但使用XML配置的Foo
。这是一个例子:
public interface Foo {
//methods here...
void fooMethod();
}
@Service("foo")
@Scope("prototype")
public class FooImpl implements Foo {
//fields and methods...
@Override
public void fooMethod() {
//...
}
}
@Service("fooCache")
@Scope
public class FooCacheImpl implements Foo {
//fields and methods...
@Override
public void fooMethod() {
//retrieves data from some cache
//...
}
}
@Service("fooWS")
@Scope("prototype")
public class FooWSImpl implements Foo {
//fields and methods...
@Override
public void fooMethod() {
//retrieves data from web service
//...
}
}
我可以通过XML配置客户端:
<bean id="fooClient" class="some.package.FooClient">
<property name="fooList">
<list>
<bean ... /> <!-- This may be fooImpl -->
<bean ... /> <!-- This may be fooCacheImpl -->
<bean ... /> <!-- This may be fooWSImpl -->
<!-- I can have more beans here -->
</list>
</property>
</bean>
我想知道这是否只能通过注释完成,而无需通过XML定义bean。像这样:
@Component
@Scope("prototype")
public class FooClient {
//which annotation(s) to use here to fill this list with FooImpl instances?
//I understand that if I have two implementations of Foo I may use a @Qualifier
//or use another list to note the different implementations.
private List<Foo> fooList;
public void bar() {
for (Foo foo : fooList) {
foo.fooMethod();
}
}
}
我认为最好是不涉及注入
ApplicationContext
或BeanFactory
的解决方案,这样FooClient
不会与Spring类紧密耦合。同样,就我而言,我不能使用任何Java EE类,例如javax.inject.Provider
,如本博客文章:Spring 2.5.x+3.0.x: Create prototype instances from code中所示。 最佳答案
怎样使用Factory Bean?
我知道您提到过,您不希望与spring过于耦合-对于工厂bean,包含列表的bean并不是那么耦合-只是工厂。
就像是
@Component("fooList")
class ListFactory<List<Foo>> implements FactoryBean, ApplicationContextAware {
ApplicationContext context;
public List<Foo>> getObject() {
List<Foo> list = new ArrayList();
list.add(context.getBean("foo");
list.add(context.getBean("foo");
return list;
}
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
public boolean isSingleton() {
return false;
}
}
@Component
@Scope("prototype")
class FooClient {
@Inject
@Named("footList")
private List<Foo> fooList;
public void bar() {
for (Foo foo : fooList) {
foo.fooMethod();
}
}
}
自己还没有尝试过,或者遇到了我需要它的情况,因此我不确定它是否可以工作。