Spring collection merge

限于喜欢 提交于 2019-12-19 10:41:54

问题


I have two lists generated with a FactoryBean and I would like to initialize a bean with the merged version of this two. Is there a way doing this?

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

There is a solution that works with static lists (http://vikdor.blogspot.hu/2012/10/using-collection-merging-in-spring-to.html), but does not work with those generated lists.


回答1:


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;
    }

}

Much less boilerplate.




回答2:


There is a sublte bug with the ListMergerFactoryBean solution above.

Config:

<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>

With this config you might be surprised when bean AwithB has the expected content of AwithC. ListA is a singleton and the getObject method alters it, therefore alters it for all users of ListMergerFactoryBean, even though the bean factory is not a singleton. The fix is to not re-use the first list in the listOfLists:

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



回答3:


After checking the SpEL-related solutions (how to extend a list in spring config) and extending the ListFactoryBean (http://ericlefevre.net/wordpress/2008/04/02/merging-lists-in-a-spring-configuration-file/) I came up with the following solution:

config:

<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;
}

}

UPDATE: I have eliminated a bug using Aron Bartle's solution. Thanks!



来源:https://stackoverflow.com/questions/14520536/spring-collection-merge

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!