java 如何在Spring中自动连接泛型类型的Bean< T>?

mbjcgjjk  于 2022-12-25  发布在  Java
关注(0)|答案(6)|浏览(164)

我有一个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>

mwyxok5s

mwyxok5s1#

简单的解决方案是升级到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);

查看下面链接中的示例和教程。

ncecgwcz

ncecgwcz2#

如果您不想升级到Spring 4,您必须按名称自动接线,如下所示:

@Autowired
@Qualifier("stringItem")
private Item<String> strItem; // Injects the stringItem bean

@Autowired
@Qualifier("integerItem")
private Item<Integer> intItem; // Injects the integerItem bean
gblwokeq

gblwokeq3#

下面是我为回答这个问题而做的一个解决方案:

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);
gkn4icbw

gkn4icbw4#

Spring自动连线策略在您的配置文件(application.xml)中定义。
如果没有定义,默认为按类型,Spring注入使用JDK反射机制。
所以List?String?和List?Item?,类型是相同的List.class,所以Spring很困惑如何注入。
和上面的人的回答一样,您应该使用point @Qualifier来告诉Spring应该注入哪个bean。
我喜欢Spring配置文件来定义bean而不是注解。

<bean>
 <property name="stringItem">
        <list>
              <....>
        </list>
 </property>
lb3vh1jj

lb3vh1jj5#

Spring4.0就是使用@Qualifier注解的答案,希望这能有所帮助

gpnt7bae

gpnt7bae6#

我相信这与泛型无关......如果您要注入两个相同类型的不同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通过解析器考虑泛型类型,这非常酷...

相关问题