Spring集合合并

时间:2013-01-25 11:07:47

标签: spring collections merge

我有两个使用FactoryBean生成的列表,我想用这两个的合并版本初始化一个bean。有没有办法做到这一点?

<bean id="listA" class="XFactoryBean" >
  ...
</bean>
<bean id="listB" class="YFactoryBean">
  ...
</bean>
<bean >
  <property name="AwithB" ...>
</bean>

有一个解决方案适用于静态列表(http://vikdor.blogspot.hu/2012/10/using-collection-merging-in-spring-to.html),但不适用于那些生成的列表。

3 个答案:

答案 0 :(得分:2)

在检查了与SpEL相关的解决方案(how to extend a list in spring config)并扩展了ListFactoryBean(http://ericlefevre.net/wordpress/2008/04/02/merging-lists-in-a-spring-configuration-file/)之后,我提出了以下解决方案:

配置:

<bean id="AwithB" class="com.util.ListMergerFactoryBean">
    <property name="listOfLists">
        <list>
            <ref bean="listA" />
            <ref bean="listB" />
        </list>
    </property>
</bean>

的java:

public class ListMergerFactoryBean implements FactoryBean<List> {

private List<List> listOfLists;

@Override
public List getObject() throws Exception {
    List mergedList = new ArrayList();
    for (List list : listOfLists) {
            mergedList.addAll(list);
    }
    return mergedList;
}

@Override
public Class<?> getObjectType() {
    return (new ArrayList()).getClass();
}

@Override
public boolean isSingleton() {
    return false;
}

public void setListOfLists(List<List> listOfLists) {
    this.listOfLists = listOfLists;
}

}

更新:我使用Aron Bartle的解决方案消除了一个错误。谢谢!

答案 1 :(得分:2)

Java @Configuration FTW:

@Configuration
public class Config {

    @Resource
    private List listA;

    @Resource
    private List listB;

    @Bean
    public List AwithB() {
        List mergedList = new ArrayList(listA);
        listB.addAll(listB);
        return mergedList;
    }

}

更少的样板。

答案 2 :(得分:2)

上面的ListMergerFactoryBean解决方案存在一个sublte错误。

配置:

<util:list id="listA" value-type="java.lang.String">
  <value>fooA</value>
  <value>barA</value>
</util:list>
<util:list id="listB" value-type="java.lang.String">
  <value>fooB</value>
  <value>barB</value>
</util:list>
<util:list id="listC" value-type="java.lang.String">
  <value>fooC</value>
  <value>barC</value>
</util:list>
<bean id="AwithB" class="com.util.ListMergerFactoryBean">
  <property name="listOfLists">
    <list>
        <ref bean="listA" />
        <ref bean="listB" />
    </list>
  </property>
</bean>
<bean id="AwithC" class="com.util.ListMergerFactoryBean">
  <property name="listOfLists">
    <list>
        <ref bean="listA" />
        <ref bean="listC" />
    </list>
  </property>
</bean>

使用此配置,当bean AwithB具有AwithC的预期内容时,您可能会感到惊讶。 ListA是一个单例,getObject方法会改变它,因此即使bean工厂不是单例,也会为ListMergerFactoryBean的所有用户改变它。解决方法是不重复使用listOfLists中的第一个列表:

@Override
public List getObject() throws Exception {
  List mergedList = new ArrayList();
  for (List list : listOfLists) {
    mergedList.addAll(list);
  }
  return mergedList;
}