我有一个bean Item<T>
,需要在@Configuration
类中自动装配。
@Configuration
public class AppConfig {
@Bean
public Item<String> stringItem() {
return new StringItem();
}
@Bean
public Item<Integer> integerItem() {
return new IntegerItem();
}
}
但是当我尝试@Autowire Item<String>
时,我会遇到异常。
"No qualifying bean of type [Item] is defined: expected single matching bean but found 2: stringItem, integerItem"
我应该如何在Spring中自动装配通用类型Item<T>
?
答案 0 :(得分:116)
简单的解决方案是升级到Spring 4.0,因为它会自动将泛型视为@Qualifier
的一种形式,如下所示:
@Autowired
private Item<String> strItem; // Injects the stringItem bean
@Autowired
private Item<Integer> intItem; // Injects the integerItem bean
事实上,您甚至可以在注入列表时自动装配嵌套泛型,如下所示:
// Inject all Item beans as long as they have an <Integer> generic
// Item<String> beans will not appear in this list
@Autowired
private List<Item<Integer>> intItems;
这是如何运作的?
新的ResolvableType
类提供了实际使用泛型类型的逻辑。您可以自己使用它来轻松导航和解析类型信息。 ResolvableType
上的大多数方法都会返回ResolvableType
,例如:
// Assuming 'field' refers to 'intItems' above
ResolvableType t1 = ResolvableType.forField(field); // List<Item<Integer>>
ResolvableType t2 = t1.getGeneric(); // Item<Integer>
ResolvableType t3 = t2.getGeneric(); // Integer
Class<?> c = t3.resolve(); // Integer.class
// or more succinctly
Class<?> c = ResolvableType.forField(field).resolveGeneric(0, 0);
查看示例&amp;教程如下链接。
希望这会对你有所帮助。
答案 1 :(得分:10)
如果你不想升级到Spring 4,你必须通过以下名称自动装配:
@Autowired
@Qualifier("stringItem")
private Item<String> strItem; // Injects the stringItem bean
@Autowired
@Qualifier("integerItem")
private Item<Integer> intItem; // Injects the integerItem bean
答案 2 :(得分:1)
Spring自动配置策略在您的配置文件(application.xml)中定义。
如果你没有定义,默认是按类型,spring注入使用JDK反射机制。
所以List?String?和List?Item?,类型是相同的List.class,所以Spring混淆了如何注入。
并且如上所述,你应该指出@Qualifier告诉spring应该注入哪些bean。
我喜欢spring configration文件来定义bean而不是Annotation。
<bean>
<property name="stringItem">
<list>
<....>
</list>
</property>
答案 3 :(得分:0)
Spring 4.0是@Qualifier注释用法的答案。希望这有帮助
答案 4 :(得分:0)
对我来说是工作!
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);
答案 5 :(得分:0)
我宁愿删除代码的耦合,而是按照this answer所述将其保留为配置。
免责声明:我是该答案的作者。
答案 6 :(得分:-1)
我认为它与泛型无关......如果你注入两个相同类型的不同bean,那么你需要提供一个限定符来帮助Spring识别它们;
......其他地方
@Configuration
@Bean
public Item stringItem() {
return new StringItem();
}
@Bean
public Item integerItem() {
return new IntegerItem();
}
如果你有这样的非泛型声明,那么你需要添加限定符来帮助Spring识别它们......
@Autowired
**@Qualifier("stringItem")**
private Item item1;
@Autowired
**@Qualifier("integerItem")**
private Item item2;
当然,在版本4及更高版本中,spring通过解析器考虑了Generic Types,这非常酷......