如何在Spring中自动装配泛型类型<T>的Bean?

use*_*518 66 java generics spring autowired spring-annotations

我有一个bean Item<T>需要在@Configuration课堂上自动装配.

@Configuration
public class AppConfig {

    @Bean
    public Item<String> stringItem() {
        return new StringItem();
    }

    @Bean
    public Item<Integer> integerItem() {
        return new IntegerItem();
    }

}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试时@Autowire Item<String>,我得到以下异常.

"No qualifying bean of type [Item] is defined: expected single matching bean but found 2: stringItem, integerItem"
Run Code Online (Sandbox Code Playgroud)

我应该如何Item<T>在Spring中自动加载通用类型?

Shi*_*mar 127

简单的解决方案是升级到Spring 4.0,因为它会自动将泛型视为一种形式@Qualifier,如下所示:

@Autowired
private Item<String> strItem; // Injects the stringItem bean

@Autowired
private Item<Integer> intItem; // Injects the integerItem bean
Run Code Online (Sandbox Code Playgroud)

事实上,您甚至可以在注入列表时自动装配嵌套泛型,如下所示:

// 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;
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?

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);
Run Code Online (Sandbox Code Playgroud)

查看以下链接中的示例和教程.

希望这对你有所帮助.

  • 这真太了不起了.我以为Type Erasure让这种事情变得不可能. (9认同)
  • 如何通过beanfactory的resolvabletype获取bean? (5认同)
  • 实际上在某些情况下,您可以在Java中获得运行时的泛型类型.一个条件,你需要有泛型类的子类.示例:父类`public class Parent <T> {}`子类`public class Child extends Parent <Integer> {}`现在:`Child c = new Child(); System.out.println(((ParameterizedType)c.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);`将打印`class java.lang.Integer` (2认同)

Ris*_*asu 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
Run Code Online (Sandbox Code Playgroud)