Mam fasolę, Item<T>
która jest wymagana do autoprzewodowania w @Configuration
klasie.
@Configuration
public class AppConfig {
@Bean
public Item<String> stringItem() {
return new StringItem();
}
@Bean
public Item<Integer> integerItem() {
return new IntegerItem();
}
}
Ale kiedy próbuję @Autowire Item<String>
, otrzymuję następujący wyjątek.
"No qualifying bean of type [Item] is defined: expected single matching bean but found 2: stringItem, integerItem"
Jak na wiosnę powinienem wpisać rodzajowy autowire Item<T>
?
public class Parent<T> {}
podklasa klasy nadrzędnejpublic class Child extends Parent<Integer> { }
i teraz:Child c = new Child(); System.out.println(((ParameterizedType)c.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
wydrukuje sięclass java.lang.Integer
Jeśli nie chcesz uaktualnić do Spring 4, musisz automatycznie połączyć się według nazwy, jak poniżej:
@Autowired @Qualifier("stringItem") private Item<String> strItem; // Injects the stringItem bean @Autowired @Qualifier("integerItem") private Item<Integer> intItem; // Injects the integerItem bean
źródło
StringItem
iIntegerItem
klasami?Poniżej znajduje się rozwiązanie, które stworzyłem, aby odpowiedzieć na to pytanie:
List<String> listItem= new ArrayList<>(); ResolvableType resolvableType = ResolvableType.forClassWithGenerics(List.class, String.class); RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setTargetType(resolvableType); beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); beanDefinition.setAutowireCandidate(true); DefaultListableBeanFactory bf = (DefaultListableBeanFactory) configurableWebApplicationContext.getBeanFactory(); bf.registerBeanDefinition("your bean name", beanDefinition); bf.registerSingleton("your bean name", listItem);
źródło
Strategia Spring autowired jest zdefiniowana w pliku konfiguracyjnym (application.xml).
jeśli nie zdefiniowałeś, domyślnie jest to typ, wtrysk sprężyny użyj mechanizmu odbicia JDK.
więc Lista? Ciąg? i List? Item ?, typ jest taki sam List.class, więc wiosna mylić, jak wstrzyknąć.
i tak jak powyżej osoby reagują, powinieneś być punktem @Qualifier, aby powiedzieć sprężynie, którą fasolę należy wstrzyknąć.
Lubię plik konfiguracyjny sprężyny, aby zdefiniować fasolę, a nie Adnotacje.
<bean> <property name="stringItem"> <list> <....> </list> </property>
źródło
Wiosna 4.0 jest odpowiedzią dzięki zastosowaniu adnotacji @Qualifier. Mam nadzieję że to pomoże
źródło
Uważam, że nie ma to nic wspólnego z lekami generycznymi ... Jeśli wstrzykujesz dwie różne ziarna tego samego typu, musisz podać kwalifikator, który pomoże Springowi je zidentyfikować;
... gdzie indziej
@Configuration @Bean public Item stringItem() { return new StringItem(); } @Bean public Item integerItem() { return new IntegerItem(); }
Jeśli masz deklaracje nieogólne, takie jak te, musisz dodać kwalifikator, aby pomóc Springowi je zidentyfikować ...
@Autowired **@Qualifier("stringItem")** private Item item1; @Autowired **@Qualifier("integerItem")** private Item item2;
Oczywiście w wersjach 4 i nowszych wiosna rozważa Typy Generyczne poprzez resolwery, co jest bardzo fajne ...
źródło