泛型类型的Spring自动装配

2023/05/13

1. 概述

在本教程中,我们介绍如何通过泛型参数注入Spring bean。

2. Spring 3.2中的自动注入与泛型

Spring从3.2开始支持泛型类型的注入

假设我们有一个名为Vehicle的抽象类和一个名为Car的具体子类:

public abstract class Vehicle {
    private String name;
    private String manufacturer;

    // getters and setters ...
}
public class Car extends Vehicle {
    private String engineType;

    // getters and setters ...
}

假设我们想将Vehicle类型的对象集合注入到某个类中:

@Autowired
private List<Vehicle> vehicles;

Spring会将所有Vehicle实例bean自动装配到此集合中,我们如何通过Java或XML配置实例化这些bean并不重要。

我们也可以使用限定符来仅获取Vehicle类型的特定bean,然后我们创建@CarQualifier并使用@Qualifier对其进行标注:


@Target({
        ElementType.FIELD, ElementType.METHOD,
        ElementType.TYPE, ElementType.PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface CarQualifier {

}

现在,我们可以在字段上使用这个注解来注入一些特定的Vehicle对象:

@Autowired
@CarQualifier
private List<Vehicle> vehicles;

在这种情况下,我们可能会创建几个Vehicle bean,但Spring只会将带有@CarQualifier注解的那些注入到上面的集合中


@SpringBootApplication
@ComponentScan("cn.tuyucheng.taketoday.dependencyinjectiontypes.model")
public class CustomConfiguration {

    @Bean
    @CarQualifier
    public Car getMercedes() {
        return new Car("E280", "Mercedes", "Diesel");
    }
}

3. Spring 4中的自动注入与泛型

假设我们有另一个名为Motorcycle的Vehicle子类:

public class Motorcycle extends Vehicle {
    private boolean twoWheeler;

    // getters and setters ...
}

现在,如果我们只想将Car类型的bean注入到我们的集合中,而不注入Motorcycle类型的bean,我们可以通过使用特定的子类作为类型参数来做到这一点:

@Autowired
private List<Car> vehicles;

自4.0版本以来,Spring允许我们使用泛型类型作为限定符,而无需显式使用注解。

在Spring 4.0之前,上面的代码不适用于Vehicle的多个子类的bean。 如果没有显式限定符,我们会得到NonUniqueBeanDefinitionException。

4. ResolvableType

泛型自动装配功能是通过ResolvableType类的帮助下在幕后工作

它是在Spring 4.0中引入的,用于封装Java Type并处理对父类、接口、泛型参数的访问,并最终解析为一个类:


@Component
public class CarHandler {

    @Autowired
    @CarQualifier
    private List<Vehicle> vehicles;

    public List<Vehicle> getVehicles() throws NoSuchFieldException {
        ResolvableType vehiclesType = ResolvableType.forField(getClass().getDeclaredField("vehicles"));
        System.out.println(vehiclesType);
        ResolvableType type = vehiclesType.getGeneric();
        System.out.println(type);
        Class<?> aClass = type.resolve();
        System.out.println(aClass);
        return this.vehicles;
    }
}

上述代码的输出将显示相应的简单类型和泛型类型:

java.util.List<cn.tuyucheng.taketoday.dependencyinjectiontypes.model.Vehicle>
cn.tuyucheng.taketoday.dependencyinjectiontypes.model.Vehicle
class cn.tuyucheng.taketoday.dependencyinjectiontypes.model.Vehicle

5. 总结

泛型类型的注入是一个强大的功能,它可以让开发人员省去分配显式限定符的工作,使代码更简洁、更易于理解。 与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章