Spring Autowiring of Generic Types – 通用类型的Spring自动接线

最后修改: 2018年 8月 27日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll see how to inject Spring beans by generic parameters.

在本教程中,我们将看到如何通过generic参数来注入Spring Bean。

2. Autowiring Generics in Spring 3.2.

2.Spring中的自动布线泛型 3.2.

Spring supports injection of generic types since version 3.2.

Spring从3.2版本开始支持通用类型的注入

Suppose we have an abstract class called Vehicle and a concrete sub-class of it called Car:

假设我们有一个名为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
}

Suppose we want to inject a list of objects of type Vehicle into some handler class:

假设我们想把一个Vehicle类型的对象列表注入某个处理程序类中。

@Autowired
private List<Vehicle> vehicles;

Spring will autowire all the Vehicle instance beans into this list. It doesn’t matter how we instantiate these beans through Java or XML configuration.

Spring将把所有的Vehicle实例Bean自动连接到这个列表中。我们如何通过Java或XML配置来实例化这些Bean并不重要。

We may also use qualifiers to get only specific beans of the Vehicle type. Then we create @CarQualifier and annotate it with @Qualifier:

我们也可以使用限定词来只获得Vehicle类型的特定Bean。然后我们创建@CarQualifier,并用@Qualifier来注解它。

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

Now we may use this annotation on our list to get only some specific Vehicles:

现在,我们可以在我们的列表上使用这个注解,只获得一些特定的Vehicles

@Autowired
@CarQualifier
private List<Vehicle> vehicles;

In this case, we may create several Vehicle beans but Spring will only inject those with @CarQualifier into the list above:

在这种情况下,我们可能会创建几个Vehicle Bean,但是Spring只会将那些带有@CarQualifier的bean注入到上述列表中:

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

3. Autowiring Generics in Spring 4.0.

3.Spring 4.0中的自动布线泛型

Suppose we have another Vehicle sub-class called Motorcycle:

假设我们有另一个Vehicle子类,叫做Motorcycle

public class Motorcycle extends Vehicle {
    private boolean twoWheeler;
    //... getters, setters etc
}

Now, if we want to inject only the Car beans into our list but no Motorcycle ones, we can do this by using the specific sub-class as a type parameter:

现在,如果我们只想将汽车Bean注入我们的列表中,而不注入摩托车Bean,我们可以通过使用特定的子类作为类型参数来实现。

@Autowired
private List<Car> vehicles;

Spring lets us use a generic type as a qualifier without the need for an explicit annotation since version 4.0.

从4.0版本开始,Spring允许我们使用通用类型作为限定符,而不需要明确的注释。

Prior to Spring 4.0, the code above wouldn’t work with beans of multiple subclasses of Vehicle. Without explicit qualifiers, we would receive a NonUniqueBeanDefinitionException.

在Spring 4.0之前,上面的代码无法适用于Vehicle的多个子类的bean。如果没有明确的限定符,我们会收到一个NonUniqueBeanDefinitionException

4. ResolvableType

4.ResolvableType

The generics autowiring feature works with the help of ResolvableType class behind the scenes.

泛型自动布线功能在幕后借助ResolvableType类来工作。

It was introduced in Spring 4.0 to encapsulate Java Type and handle access to supertypes, interfaces, generic parameters and finally resolve to a Class:

它是在Spring 4.0中引入的,用于封装Java类型,处理对超类型、接口、通用参数的访问,并最终解析到一个Class。

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

The output of the above code would show the corresponding simple and generic types:

上述代码的输出将显示相应的简单和通用类型。

java.util.List<com.example.model.Vehicle>
com.example.model.Vehicle
class com.example.model.Vehicle

5. Conclusion

5.总结

Injection of generic types is a powerful feature, which saves the developer the effort of assigning explicit qualifiers, making code cleaner and much more understandable.

通用类型的注入是一个强大的功能,它节省了开发者分配显式限定符的努力,使代码更干净,更容易理解。

As always the code can be found over on GitHub.

像往常一样,代码可以在GitHub上找到over