Java 如何在 Spring 中自动装配泛型 <T> 类型的 Bean?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22603291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Autowire Bean of generic type <T> in Spring?
提问by user3374518
I have a bean Item<T>
which is required to be autowired in a @Configuration
class.
我有一个Item<T>
需要在@Configuration
类中自动装配的 bean 。
@Configuration
public class AppConfig {
@Bean
public Item<String> stringItem() {
return new StringItem();
}
@Bean
public Item<Integer> integerItem() {
return new IntegerItem();
}
}
But when I try to @Autowire Item<String>
, I get following exception.
但是当我尝试时@Autowire Item<String>
,我得到以下异常。
"No qualifying bean of type [Item] is defined: expected single matching bean but found 2: stringItem, integerItem"
How should I Autowire generic type Item<T>
in Spring?
我应该如何Item<T>
在 Spring 中自动装配泛型类型?
采纳答案by Shishir Kumar
Simple solution is to upgrade to Spring 4.0as it will automatically consider generics as a form of @Qualifier
, as below:
简单的解决方案是升级到Spring 4.0,因为它会自动将泛型视为 的一种形式@Qualifier
,如下所示:
@Autowired
private Item<String> strItem; // Injects the stringItem bean
@Autowired
private Item<Integer> intItem; // Injects the integerItem bean
Infact, you can even autowire nested generics when injecting into a list, as below:
事实上,您甚至可以在注入列表时自动装配嵌套泛型,如下所示:
// 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;
How this Works?
这是如何运作的?
The new ResolvableType
class provides the logic of actually working with generic types. You can use it yourself to easily navigate and resolve type information. Most methods on ResolvableType
will themselves return a ResolvableType
, for example:
新ResolvableType
类提供了实际使用泛型类型的逻辑。您可以自己使用它来轻松导航和解析类型信息。大多数方法ResolvableType
本身都会返回 a 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);
Check out the Examples & Tutorials at below links.
在下面的链接中查看示例和教程。
Hope this helps you.
希望这对你有帮助。
回答by Rishav Basu
If you dont want to upgrade to Spring 4 you have to autowire by name as below :
如果您不想升级到 Spring 4,则必须按名称自动装配,如下所示:
@Autowired
@Qualifier("stringItem")
private Item<String> strItem; // Injects the stringItem bean
@Autowired
@Qualifier("integerItem")
private Item<Integer> intItem; // Injects the integerItem bean
回答by shikjohari
Spring 4.0 is the answer with the @Qualifier annotation usage. Hope this helps
Spring 4.0 是@Qualifier 注释用法的答案。希望这可以帮助
回答by zg_spring
Spring autowired strategy is defined in your configration file(application.xml).
Spring 自动装配策略在您的配置文件 (application.xml) 中定义。
if you don't defined, default is by Type, spring inject use JDK reflect mechanism.
如果你没有定义,默认是按类型,spring 注入使用 JDK 反射机制。
so List?String? and List?Item?, the type is same List.class, so spring confused how to inject.
所以列表?字符串?和List?Item?,类型是一样的List.class,所以spring很迷茫怎么注入。
and as above persons response, you should be point @Qualifier to tell spring which bean should be inject.
正如上面的人的反应,你应该指向@Qualifier 告诉 spring 应该注入哪个 bean。
i like spring configration file to define bean rather then Annotation.
我喜欢 spring 配置文件来定义 bean 而不是 Annotation。
<bean>
<property name="stringItem">
<list>
<....>
</list>
</property>
回答by Ramkumar S
I believe it has nothing to with generics... If you are injecting two different beans of same type then you need to provide a qualifier to help Spring identify them;
我相信它与泛型无关……如果您要注入两个相同类型的不同 bean,那么您需要提供一个限定符来帮助 Spring 识别它们;
... Elsewhere
... 在别处
@Configuration
@Bean
public Item stringItem() {
return new StringItem();
}
@Bean
public Item integerItem() {
return new IntegerItem();
}
If you have a non-generic declarations like these then you need to add qualifier to help Spring identify them...
如果您有像这样的非通用声明,那么您需要添加限定符来帮助 Spring 识别它们......
@Autowired
**@Qualifier("stringItem")**
private Item item1;
@Autowired
**@Qualifier("integerItem")**
private Item item2;
Of course, in versions 4 and above spring considers the Generic Types through the resolvers which is very cool...
当然,在版本 4 及更高版本中,spring 通过解析器考虑通用类型,这非常酷......
回答by howard791006
Below is a solution I made to answer this question:
以下是我为回答这个问题而提出的解决方案:
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);