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

     2023-02-26     149

关键词:

【中文标题】如何在 Spring 中自动装配泛型类型 <T> 的 Bean?【英文标题】:How to Autowire Bean of generic type <T> in Spring? 【发布时间】:2022-01-24 08:02:45 【问题描述】:

我有一个 bean Item&lt;T&gt; 需要在 @Configuration 类中自动装配。

@Configuration
public class AppConfig 

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

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


但是当我尝试@Autowire Item&lt;String&gt; 时,我得到以下异常。

"No qualifying bean of type [Item] is defined: expected single matching bean but found 2: stringItem, integerItem"

我应该如何在 Spring 中自动装配泛型类型 Item&lt;T&gt;

【问题讨论】:

【参考方案1】:

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

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

Spring Framework 4.0 and Java Generics Spring and Autowiring of Generic Types

希望对你有所帮助。

【讨论】:

这太棒了。我认为类型擦除使这种事情成为不可能。 如何从 beanfactory 通过 resolvabletype 获取 bean? @JohnStricler 我也认为这不能安全地完成。我还没有检查 ResolvableType 的实现,但这是否意味着我们现在可以安全地获得泛型类型? 实际上在某些情况下,您可以在 Java 的运行时获取泛型类型。一个条件,你需要有泛型类的子类。示例:父类 public class Parent&lt;T&gt; 子类 public class Child extends Parent&lt;Integer&gt; 现在:Child c = new Child(); System.out.println(((ParameterizedType)c.getClass().getGenericSuperclass()).getActualTypeArguments()[0]); 将打印 class java.lang.Integer 这是否适用于包扫描 bean 自动配置?我不这么认为。【参考方案2】:

如果您不想升级到 Spring 4,您必须按以下名称自动装配:

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

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

【讨论】:

你的意思是直接使用具体的StringItem & IntegerItem 类吗?【参考方案3】:

以下是我为回答这个问题而制定的解决方案:


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

【讨论】:

BTW in Spring 5+【参考方案4】:

Spring 自动装配策略在您的配置文件(application.xml)中定义。

如果不定义,默认是按类型,spring注入使用JDK反射机制。

所以列表?字符串?和List?Item?,类型是一样的List.class,所以spring很困惑如何注入。

和上面的人的反应一样,你应该点@Qualifier来告诉spring应该注入哪个bean。

我喜欢 spring 配置文件来定义 bean 而不是 Annotation。

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

【讨论】:

【参考方案5】:

Spring 4.0 是使用 @Qualifier 注释的答案。希望这会有所帮助

【讨论】:

【参考方案6】:

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

【讨论】:

使用构造函数自动装配泛型类型 [Spring 4.2.5]

】使用构造函数自动装配泛型类型[Spring4.2.5]【英文标题】:Autowiringgenerictypeswithconstructor[Spring4.2.5]【发布时间】:2016-08-1703:11:57【问题描述】:我是Spring新手,正在尝试像本文http://www.ibm.com/developerworks/library/j-genericdao/中那样实... 查看详情

如何在 Spring Boot 中实现通用 JPA 存储库 - 它可以自动装配到任何实体/类类型的 Spring 服务中

】如何在SpringBoot中实现通用JPA存储库-它可以自动装配到任何实体/类类型的Spring服务中【英文标题】:HowtoimplementGenericJPARepositoryinSpringBoot-Whichcanbeautowiredintospringservicesforanyentity/classtype【发布时间】:2016-02-0408:07:27【问题描述】... 查看详情

Spring JUnit:如何在自动装配组件中模拟自动装配组件

】SpringJUnit:如何在自动装配组件中模拟自动装配组件【英文标题】:SpringJUnit:HowtoMockautowiredcomponentinautowiredcomponent【发布时间】:2013-10-1810:25:24【问题描述】:我有一个我想测试的Spring组件,并且这个组件有一个自动装配的属... 查看详情

在spring中通过构造自动装配--constructor

在Spring中,可以使用“通过构造自动装配”,实际上是按构造函数的参数类型自动装配。 这意味着,如果一个bean的数据类型与其他bean的构造器参数的数据类型是相同的,那么将自动装配。 packageauto_constructor;/***Createdbyluo... 查看详情

spring入门第六课

XML配置里的Bean自动装配SpringIOC容器可以自动装配Bean。需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式ByType(根据类型自动装配):若IOC容器中有多个与目标Bean类型一致的的Bean,在这种情况下,Spring将无法判定哪... 查看详情

spring-bean的自动装配

7、bean的自动装配自动装配是Spring满足bean依赖的一种方式!Spring会在上下文中自动寻找,并自动给bean装配属性!在Spring中有三种装配的方式在xml中显示的配置在java中显示配置隐式的自动装配bean【重要】7.1、自动装配环境搭建一... 查看详情

如何在 Spring Boot 中自动装配 Hibernate SessionFactory

】如何在SpringBoot中自动装配HibernateSessionFactory【英文标题】:HowtoautowireHibernateSessionFactoryinSpringboot【发布时间】:2017-10-0906:56:27【问题描述】:我已经创建了一个SpringBoot应用程序,我想处理HibernateSessionFactory,所以在我的服务类... 查看详情

spring-装配

Spring装配有三种方式:基于XML的显式配置基于注解的自动装配在java中进行显示配置1、基于注解的自动装配Spring从组件扫描和自动装配两个角度实现自动转配组件扫描:Spring会自动发现应用上下文中所创建的bean,配置时需要指定... 查看详情

spring4.0学习笔记——自动装配

SpringIOC容器可以自动装配Bean,需要做的是在<bean>的autowire属性里指定自动装配的模式1)byType根据类型自动装配,若IOC容器中有多个目标Bean类型一致的Bean,Spring将无法判定哪个Bean最适合该属性,不能执行自动装配2)byName根据... 查看详情

如何使用 Mockito 在 Spring 中模拟自动装配的 @Value 字段?

】如何使用Mockito在Spring中模拟自动装配的@Value字段?【英文标题】:HowdoImockanautowired@ValuefieldinSpringwithMockito?【发布时间】:2014-06-0311:22:51【问题描述】:我正在使用Spring3.1.4.RELEASE和Mockito1.9.5。在我的春季课程中,我有:@Value("#... 查看详情

spring的装配

Spring装配有三种方式:基于XML的显式配置基于注解的自动装配在java中进行显示配置1、基于注解的自动装配Spring从组件扫描和自动装配两个角度实现自动转配组件扫描:Spring会自动发现应用上下文中所创建的bean,配置时需要指定... 查看详情

spring探究-----自动装配bean详解(代码片段)

...bean,若有多个则无法完成自动装配<beanid="student"class="com.spring.autowire.Student"autowire="byName" 查看详情

<spring实战>3:最小化springxml配置

1自动装配Bean属性1.14种类型的自动装配byName:把与Bean的属性具有相同名字或ID的其他Bean自动装配到Bean的对应属性中byType:把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中constructor:把与Bean的构造器入参具有相... 查看详情

如何在Spring bean中传递类构造函数参数由注释自动装配

】如何在Springbean中传递类构造函数参数由注释自动装配【英文标题】:HowtopassclassconstructorparametersinSpringbeanAutowiredbyannotations【发布时间】:2015-02-2000:19:24【问题描述】:没有IOC容器的正常方法是:newUser("Names",22);这里的参数值是... 查看详情

如何在 spring-servlet.xml 中自动装配 crud 存储库?

】如何在spring-servlet.xml中自动装配crud存储库?【英文标题】:Howtoautowirecrudrepositoryinspring-servlet.xml?【发布时间】:2017-09-0102:08:52【问题描述】:当我们在springmvc中使用crud存储库时出现以下错误4352[localhost-startStop-1]错误org.springfra... 查看详情

spring-----注解实现自动装配(自动匹配属性类型)@autowired和autowire

1.注解:实现Bean的属性装配实现注解开发自动装配步骤:  1.导入XML配置文件头部约束  增加命名空间 2.注解的支持<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http: 查看详情

spring之自动装配

一、自动装配模型下面是自动连接模式,可以用来指示Spring容器使用自动连接进行依赖注入。您可以使用元素的autowire属性为bean定义指定autowire模式。可以使用 byType 或者 constructor 自动装配模式来连接数组和其他... 查看详情

spring中基于xml的自动装配(自动赋值)(代码片段)

Spring中基于XML的自动装配手动赋值过程演示自动装配(自动赋值)autowire的默认属性是default,default等价于no按照某种规则自动装配autowire="byName"autowire="byType"autowire="constructor"集合自动装配----集合里面存放的... 查看详情