Весенний список бобов по типу - PullRequest
8 голосов
/ 20 сентября 2009

Есть ли способ, которым я могу автоматически заполнить список всеми компонентами типа И любым из его подтипов? У меня есть метод установки, который выглядит так:

setMyProp(List<MyType> list)

И я хотел бы автоматически подключать любые компоненты MyType и все подклассы MyType.

Спасибо, Джефф

Ответы [ 5 ]

25 голосов
/ 20 сентября 2009

Да, вы можете сделать это. Весенние документы говорят:

Также возможно предоставить все бобы определенного типа из ApplicationContext, добавив аннотация к полю или методу, который ожидает массив этого типа.

Обратите внимание, что в нем говорится, что вы должны ожидать массив, а не список. Это имеет смысл, потому что стирание универсального типа означает, что список может не работать во время выполнения. Тем не менее, возьмите следующий юнит-тест, который работает:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  

    <bean class="test.Test.TypeB"/>
    <bean class="test.Test.TypeC"/>
    <bean class="test.Test.TypeD"/>
</beans>

и этот юнит-тест:

package test;

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class Test {

    private @Autowired List<TypeA> beans;

    @org.junit.Test
    public void test() {
        assertNotNull(beans);
        assertEquals(2, beans.size());
        for (TypeA bean : beans) {
            assertTrue(bean instanceof TypeA);
        }
    }       

    public static interface TypeA {}
    public static class TypeB implements TypeA {}
    public static class TypeC extends TypeB {}
    public static class TypeD {}

}

Итак, официально вы должны автоматически подключать TypeA[], а не List<TypeA>, но список работает хорошо.

5 голосов
/ 20 сентября 2009

Если допустимо заполнить список из кода приложения, а не из файла определения компонента, вы можете использовать org.springframework.beans.factory.xml.XmlBeanFactory и задать его «getBeansOfType( MyType.class )». Это дает вам все бины типа (и подтипа) MyType.

3 голосов
/ 22 сентября 2009

Если вы можете использовать @Autowired внутри кода, который вы хотите заполнить, вы можете безопасно использовать путь, упомянутый skaffman. Если вы настаиваете на конфигурации XML, есть небольшая библиотека под названием Hera для достижения этой цели. По сути конфигурация описанного вами сценария выглядит так:

<bean id="client" class="..">
    <property name="injectDynamicListHere">
        <hera:list class="my.custom.SuperType" />
    </property>
</bean>

Это внедрит все bean-компоненты Spring верхнего уровня, реализующие SuperType как List в клиентский bean-компонент.

0 голосов
/ 29 сентября 2015

Из-за устаревшего кода и отсутствия @Autowired я решаю его так:

MyBean implements ApplicationContextAware{

  @Override
  public void setApplicationContext(ApplicationContext ctx) throws BeansException {
    final Map<String, HttpRequestHandlerTemplate> beansOfType = ctx.getBeansOfType(RequiredBean.class);
    ...
}
0 голосов
/ 20 сентября 2009

Краткий ответ: нет.

Длинный ответ: Обобщения Java работают по типу стирания, что означает, что во время выполнения этот параметр является просто списком, а не списком универсального типа. Таким образом, вы не можете понять, что он имеет тип параметра MyType, поэтому невозможно реализовать это поведение.

При этом есть альтернативные способы сделать это. Наиболее очевидным, по-видимому, является прослушивание создания bean-компонента, а затем выяснение, принадлежат ли они MyType (или подклассам), а затем сохранение ссылки.

Вероятно, есть несколько способов сделать это. Одним из них является создание постпроцессора бина . Таким образом, вы будете получать уведомления о каждом созданном бине.

...