Перейти к основному содержимому

Spring Autowiring универсальных типов

· 3 мин. чтения

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
}

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

@Autowired
private List<Vehicle> vehicles;

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

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

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

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

@Autowired
@CarQualifier
private List<Vehicle> vehicles;

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

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

3. Автомонтирование дженериков в Spring 4.0.

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

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

Теперь, если мы хотим внедрить в наш список только bean -компоненты Car , а не Motorcycle , мы можем сделать это, используя конкретный подкласс в качестве параметра типа:

@Autowired
private List<Car> vehicles;

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

До Spring 4.0 приведенный выше код не работал с bean-компонентами нескольких подклассов Vehicle . Без явных квалификаторов мы получили бы 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. Вывод

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

Как всегда, код можно найти на GitHub .