2009-09-20 5 views
7

Czy jest jakiś sposób na wiosnę, że mogę automatycznie wypełnić listę wszystkimi ziarnami fasoli typu I dowolnego z jej podtypów? Mam metody setter, który wygląda jak:Fasola z listy wiosennej według typu

setMyProp(List<MyType> list) 

I chciałbym autowire w jakichkolwiek ziaren MyType oraz wszystkich podklas MyType.

Dzięki Jeff

+0

Jak chcesz tę listę do pracy z prototypami? Jeśli zawiera tylko jedną instancję, dodaj każdą instancję (wyciek pamięci) lub wróć przez jakąś słabą listę referencyjną. –

+0

wszystkie ziarna będą pojedynczo w moim przypadku. –

Odpowiedz

24

Tak, możesz to zrobić. Docs sprężyste znaczy:

Jest również możliwe podanie wszystkich ziaren konkretnego rodzaju z ApplicationContext dodając adnotacje na polu lub w sposób, który oczekuje szereg tego typu.

Należy pamiętać, że trzeba się spodziewać tablicy, a nie listy. Ma to sens, ponieważ ogólny typ wymazania oznacza, że ​​lista może nie działać w środowisku wykonawczym. Jednak podjąć następujące badanej jednostki, która działa:

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

i ten test Jednostka:

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

} 

Więc oficjalnie, masz za zadanie autowire TypeA[], nie List<TypeA>, ale lista działa dobrze.

0

Krótka odpowiedź: nie.

Długa odpowiedź: Generics Java działa według typu wymazania, co oznacza, że ​​w czasie wykonywania ten parametr jest po prostu listą, a nie listą typu ogólnego. W związku z tym nie można wykluczyć, że ma on typ parametru MyType, więc nie byłoby możliwe zaimplementowanie tego zachowania.

Mimo to istnieją alternatywne sposoby robienia tego. Najbardziej oczywistym wydaje się być słuchanie tworzenia fasoli, a następnie sprawdzanie, czy są z MyType (lub podklas), a następnie zachowanie odniesienia.

Istnieje prawdopodobnie kilka sposobów, aby to zrobić. Jeden to creating a bean post-processor. W ten sposób otrzymasz powiadomienie o każdym utworzonym komponencie.

+3

Informacje o typie dla parametrów metody nie zostały całkowicie usunięte i nadal są dostępne dla środowiska wykonawczego. Dostęp do tego można uzyskać za pomocą metody Method lub Constructor getGenericParameterTypes. –

+0

@mik: tak, ale mówił o parametrze funkcji, w której takie informacje nie są dostępne. – cletus

5

Jeśli dopuszczalne jest wypełnienie listy z kodu aplikacji, a nie z poziomu pliku definicji fasoli, można użyć wartości org.springframework.beans.factory.xml.XmlBeanFactory i poprosić o "getBeansOfType(MyType.class)". To daje wszystkie fasole typu (i podtypu) z MyType.

+1

To faktycznie działa dla wszystkich klas implementujących ListableBeanFactory (http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/factory/ListableBeanFactory.html#getBeansOfType%28java.lang.Class% 29) –

3

Jeśli możesz użyć kodu @Autowired w zapełnionym kodzie, możesz bezpiecznie korzystać ze sposobu wspomnianego przez skaffmana. Jeśli nalegasz na konfigurację XML, do osiągnięcia tego celu służy mała biblioteka o nazwie Hera. konfiguracja Esentially scenariusza opisanego przez ciebie wygląda następująco:

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

To będzie wstrzyknąć całą wiosnę fasolę najwyższego poziomu wykonawczych SuperType jako List do fasoli klienta.

+0

fajne, dzięki. Udało mi się użyć @Autowired w kodzie, ale dobrze o tym wiedzieć. –

+1

Być może jedną z drobniejszych rzeczy do dodania jest to, że lista Hera respektuje adnotacje @Odblokowane. implementacja interfejsu Uporządkowany w celu umożliwienia określenia kolejności wstrzykiwanych ziaren. –

0

Ze względu na starszych kod i brakujących @Autowired rozwiązać to lubią:

MyBean implements ApplicationContextAware{ 

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