Как я могу использовать Spring XML-конфигурацию для установки свойства bean со списком всех beans определенного типа?

У меня есть следующая конфигурация XML:

<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>

<bean id="tasks" class="java.util.ArrayList">
    <constructor-arg>
        <list>
            <ref bean="bean1" />
            <ref bean="bean2" />                
        </list>
    </constructor-arg>
</bean>

<bean id="list" class="Comp">
    <property name="tasks" ref="tasks"/>
</bean>

"Задачи" содержат все beans типа Simple. Проблема заключается в том, что я могу забыть добавить Simple bean, который я настроил для этого списка.

Я мог бы сделать это программно, используя

Map map = context.getBeansOfType(Simple.class);

и установив список bean с извлеченным beans.

Есть ли способ сделать это, используя только конфигурацию XML?

Ответ 1

Ваш файл контекста должен выглядеть так:

<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>

<bean id="list" class="Comp" autowire="byType"/>

Обратите внимание на добавление autowire="byType" и документацию по автообновлению.

Ответ 2

Я бы предложил написать собственный FactoryBean для создания такого списка. Это можно было бы повторно использовать, а затем настраивать с помощью только XML. FactoryBean будет выглядеть как

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;

public class CollectingListFactoryBean implements FactoryBean, ApplicationContextAware {
    private ApplicationContext appCtx;
    private Class type;

    public Object getObject() {
        Assert.notNull(type, "type must be initialized");
        List result = new ArrayList();
        result.addAll(appCtx.getBeansOfType(type).values());
        return result;
    }

    public Class getObjectType() {
        return List.class;
    }

    public boolean isSingleton() {
        return false;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.appCtx = applicationContext;
    }

    public void setType(Class type) {
        this.type = type;
    }
}

Тогда ваша конфигурация XML будет

<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>

<bean id="tasks" class="CollectingListFactoryBean">
    <property name="type" value="Simple" />
</bean>

<bean id="list" class="Comp">
    <property name="tasks" ref="tasks"/>
</bean>

ПРИМЕЧАНИЕ. У меня не было времени проверить пример выше. Я просто использовал код, который у меня уже был как шаблон.;) Особенно я не уверен, что этот путь работает Simple как аргумент Class для свойства type. Просто попробуй. В худшем случае вам нужно будет использовать String как тип свойства и использовать Class.forName(type) для получения вашего класса. Но я предполагаю, что Spring делает это преобразование для вас.

EDIT. Хотя это решение должно работать, я рекомендую ответить Роберту Мунтяну.