2009-09-20 12 views
7

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

setMyProp(List<MyType> list) 

И я хотел бы autowire в любых бобах MyType и все подклассы MyType.

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

+0

Как вы хотите этот список, чтобы работать с прототипами? Если он содержит только один экземпляр, добавьте каждый экземпляр (утечку памяти) или вернитесь в какой-то слабенький список ссылок. –

+0

все бобы будут синглонами в моем случае –

ответ

24

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

Кроме того, можно обеспечить все бобы определенного типа из 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 {} 

} 

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

0

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

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

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

Возможно, есть несколько способов сделать это. Один - creating a bean post-processor. Таким образом вы получите уведомление обо всех созданных компонентах.

+3

Информация о типе параметров метода не полностью удалена и доступна для выполнения. Вы можете получить доступ к нему с помощью метода getGenericParameterTypes метода или конструктора. –

+0

@mik: да, но он говорил о параметре функции, где такой информации нет. – cletus

5

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

+1

Это действительно работает для всех классов, реализующих ListableBeanFactory (http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/factory/ListableBeanFactory.html#getBeansOfType%28java.lang.Class% 29) –

3

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

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

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

+0

круто, спасибо. Я смог использовать @Autowired в коде, но это хорошо знать. –

+1

Возможно, одна незначительная вещь, которую нужно добавить, состоит в том, что список Hera уважает @Ordered аннотации и. реализуя упорядоченный интерфейс, позволяющий определять порядок впрыскиваемых компонентов. –

0

Благодаря унаследованного кода и пропавших без вести @Autowired Решаю это нравится:

MyBean implements ApplicationContextAware{ 

    @Override 
    public void setApplicationContext(ApplicationContext ctx) throws BeansException { 
    final Map<String, HttpRequestHandlerTemplate> beansOfType = ctx.getBeansOfType(RequiredBean.class); 
    ... 
}