1. 概述
在本教程中,我們將學習如何通過泛型參數注入 Spring Bean。
2. 在 Spring 3.2 中使用通配符注入
Spring 從 3.2 版本開始支持注入泛型類型。
假設我們有一個名為 Vehicle 的抽象類,以及它的一個具體子類 Car。
public abstract class Vehicle {
private String name;
private String manufacturer;
// ... getters, setters etc
}public class Car extends Vehicle {
private String engineType;
// ... getters, setters etc
}假設我們要將若干個類型為 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 {
}現在我們可以使用此標註來從我們的列表中獲取特定的 車輛:
@Autowired
@CarQualifier
private List<Vehicle> vehicles;在這種情況下,我們可能會創建多個 Vehicle Bean,但 Spring 只會將帶有 @CarQualifier 標記的 Bean 注入到上述列表中。
public class CustomConfiguration {
@Bean
@CarQualifier
public Car getMercedes() {
return new Car("E280", "Mercedes", "Diesel");
}
}3. 在 Spring 4.0 中自動裝配泛型。
假設我們還有一個名為 Motorcycle 的 Vehicle 子類:
public class Motorcycle extends Vehicle {
private boolean twoWheeler;
//... getters, setters etc
}現在,如果我們想要只將 Car 類型的豆子注入到我們的列表中,而不注入任何 Motorcycle 類型的豆子,我們可以通過使用特定的子類作為類型參數來實現:
@Autowired
private List<Car> vehicles;
Spring 允許我們使用泛型類型作為限定符,無需在版本 4.0 之後進行顯式註解。
在 Spring 4.0 之前,上述代碼無法與 Vehicle 類及其子類的多個子類中的 Bean 一起使用。 缺少顯式限定符,我們會收到 NonUniqueBeanDefinitionException。
4. 可解析類型 (ResolvableType)
泛型自動裝入功能借助可解析類型類在幕後工作。
它在 Spring 4.0 中引入,用於封裝 Java 類型並處理對超類型、接口、泛型參數以及最終解析為類的訪問。
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);上述代碼的輸出將顯示相應的簡單和通用類型:
java.util.List<com.example.model.Vehicle>
com.example.model.Vehicle
class com.example.model.Vehicle
5. 結論
類型注入是一種強大的特性,它省去了開發者手動指定限定符的精力,使代碼更簡潔、更易於理解。