«1. Обзор

В этом руководстве мы увидим, как внедрять bean-компоненты Spring по общим параметрам.

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
}

@Autowired
private List<Vehicle> vehicles;

Предположим, мы хотим внедрить список объектов типа Vehicle в некоторый класс-обработчик: ~~ ~

Spring автоматически подключит все bean-компоненты экземпляров Vehicle в этот список. Неважно, как мы создаем экземпляры этих bean-компонентов с помощью конфигурации Java или XML.

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

Мы также можем использовать квалификаторы, чтобы получить только определенные bean-компоненты типа Vehicle. Затем мы создаем @CarQualifier и аннотируем его с помощью @Qualifier:

@Autowired
@CarQualifier
private List<Vehicle> vehicles;

Теперь мы можем использовать эту аннотацию в нашем списке, чтобы получить только некоторые определенные автомобили:

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

В этом случае мы можем создать несколько компонентов Vehicle но Spring вставит в список выше только тех, у кого есть @CarQualifier:

3. Autowiring Generics в Spring 4.0.

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

Предположим, у нас есть еще один подкласс Vehicle с именем Motorcycle:

@Autowired
private List<Car> vehicles;

Теперь, если мы хотим внедрить в наш список только bean-компоненты Car, а не Motorcycle, мы можем сделать это с помощью специального подкласса в качестве параметра типа:

Начиная с версии 4.0 Spring позволяет нам использовать общий тип в качестве квалификатора без необходимости явной аннотации.

До Spring 4.0 приведенный выше код не работал с bean-компонентами нескольких подклассов Vehicle. Без явных квалификаторов мы получили бы исключение NonUniqueBeanDefinitionException.

4. ResolvableType

Функция автоматического связывания дженериков работает с помощью класса ResolvableType за кулисами.

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

Он был представлен в Spring 4.0 для инкапсуляции типа Java и обработки доступа к супертипам, интерфейсам, универсальным параметрам и, наконец, разрешению в класс:

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

Вывод приведенного выше кода будет отображать соответствующие простые и универсальные типы. :

5. Заключение

Внедрение универсальных типов — это мощная функция, которая избавляет разработчика от необходимости назначать явные квалификаторы, делая код чище и намного понятнее.