从这个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();
        }
    }
}


我认为最好是不涉及注入ApplicationContextBeanFactory的解决方案,这样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();
        }
    }
}


自己还没有尝试过,或者遇到了我需要它的情况,因此我不确定它是否可以工作。

10-07 13:21
查看更多