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

Spring – Внедрение коллекций

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

1. Введение

В этом руководстве мы собираемся показать, как внедрять коллекции Java с помощью среды Spring .

Проще говоря, мы продемонстрируем примеры с интерфейсами коллекции List, Map, Set .

2. Список с @Autowired

Давайте создадим пример bean-компонента:

public class CollectionsBean {

@Autowired
private List<String> nameList;

public void printNameList() {
System.out.println(nameList);
}
}

Здесь мы объявили свойство nameList для хранения списка строковых значений .

В этом примере мы используем внедрение полей для nameList . Поэтому ставим аннотацию @Autowired .

Чтобы узнать больше о внедрении зависимостей или различных способах его реализации, ознакомьтесь с этим руководством .

После этого мы регистрируем CollectionsBean в классе настройки конфигурации:

@Configuration
public class CollectionConfig {

@Bean
public CollectionsBean getCollectionsBean() {
return new CollectionsBean();
}

@Bean
public List<String> nameList() {
return Arrays.asList("John", "Adam", "Harry");
}
}

Помимо регистрации CollectionsBean , мы также вводим новый список, явно инициализируя и возвращая его как отдельную конфигурацию @Bean .

Теперь мы можем проверить результаты:

ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class);
CollectionsBean collectionsBean = context.getBean(
CollectionsBean.class);
collectionsBean.printNameList();

Вывод метода printNameList():

[John, Adam, Harry]

3. Установить с внедрением конструктора

Чтобы настроить тот же пример с коллекцией Set , давайте изменим класс CollectionsBean :

public class CollectionsBean {

private Set<String> nameSet;

public CollectionsBean(Set<String> strings) {
this.nameSet = strings;
}

public void printNameSet() {
System.out.println(nameSet);
}
}

На этот раз мы хотим использовать внедрение конструктора для инициализации свойства nameSet . Это требует также изменений в классе конфигурации:

@Bean
public CollectionsBean getCollectionsBean() {
return new CollectionsBean(new HashSet<>(Arrays.asList("John", "Adam", "Harry")));
}

4. Карта с внедрением сеттера

Следуя той же логике, давайте добавим поле nameMap для демонстрации внедрения карты:

public class CollectionsBean {

private Map<Integer, String> nameMap;

@Autowired
public void setNameMap(Map<Integer, String> nameMap) {
this.nameMap = nameMap;
}

public void printNameMap() {
System.out.println(nameMap);
}
}

На этот раз у нас есть метод setter, чтобы использовать инъекцию зависимостей setter . Нам также нужно добавить код инициализации карты в класс конфигурации:

@Bean
public Map<Integer, String> nameMap(){
Map<Integer, String> nameMap = new HashMap<>();
nameMap.put(1, "John");
nameMap.put(2, "Adam");
nameMap.put(3, "Harry");
return nameMap;
}

Результаты после вызова метода printNameMap() :

{1=John, 2=Adam, 3=Harry}

5. Внедрение ссылок на компоненты

Давайте рассмотрим пример, в котором мы вводим ссылки на bean-компоненты как элементы коллекции.

Во-первых, давайте создадим bean-компонент:

public class ForEachBean {

private String name;

// constructor
}

И добавьте список ForEachBean в качестве свойства в класс CollectionsBean :

public class CollectionsBean {

@Autowired(required = false)
private List<ForEachBean> beanList;

public void printBeanList() {
System.out.println(beanList);
}
}

Затем мы добавляем фабричные методы конфигурации Java для каждого элемента ForEachBean :

@Configuration
public class CollectionConfig {

@Bean
public ForEachBean getElement() {
return new ForEachBean("John");
}

@Bean
public ForEachBean getAnotherElement() {
return new ForEachBean("Adam");
}

@Bean
public ForEachBean getOneMoreElement() {
return new ForEachBean("Harry");
}

// other factory methods
}

Контейнер Spring внедряет отдельные компоненты типа ForEachBean в одну коллекцию.

Чтобы проверить это, мы вызываем метод collectionsBean.printBeanList() . Вывод показывает имена bean-компонентов в виде элементов списка:

[John, Harry, Adam]

Теперь давайте рассмотрим сценарий, когда ForEachBean отсутствует . Если в контексте приложения не зарегистрирован ForEachBean , Spring выдаст исключение из-за отсутствия требуемой зависимости.

Мы можем использовать @Autowired(required = false) , чтобы пометить зависимость как необязательную. Вместо создания исключения beanList не будет инициализирован, и его значение останется нулевым .

Если нам нужен пустой список вместо null, мы можем инициализировать beanList новым ArrayList:

@Autowired(required = false)
private List<ForEachBean> beanList = new ArrayList<>();

5.1. Использование @Order для сортировки компонентов

Мы можем указать порядок bean-компонентов при внедрении в коллекцию .

Для этого используем аннотацию @Order и указываем индекс:

@Configuration
public class CollectionConfig {

@Bean
@Order(2)
public ForEachBean getElement() {
return new ForEachBean("John");
}

@Bean
@Order(3)
public ForEachBean getAnotherElement() {
return new ForEachBean("Adam");
}

@Bean
@Order(1)
public ForEachBean getOneMoreElement() {
return new ForEachBean("Harry");
}
}

Контейнер Spring сначала введет bean-компонент с именем «Harry» , так как он имеет наименьшее значение порядка.

Затем он внедрит бин «John» и, наконец, бин «Adam» :

[Harry, John, Adam]

Узнайте больше о @Order в этом руководстве .

5.2. Использование @Qualifier для выбора компонентов

Мы можем использовать @Qualifier , чтобы выбрать bean-компоненты для внедрения в конкретную коллекцию, которая соответствует имени @Qualifier .

Вот как мы используем его для точки впрыска:

@Autowired
@Qualifier("CollectionsBean")
private List<ForEachBean> beanList;

Затем мы помечаем тем же @Qualifier bean-компоненты, которые мы хотим внедрить в список :

@Configuration
public class CollectionConfig {

@Bean
@Qualifier("CollectionsBean")
public ForEachBean getElement() {
return new ForEachBean("John");
}

@Bean
public ForEachBean getAnotherElement() {
return new ForEachBean("Adam");
}

@Bean
public ForEachBean getOneMoreElement() {
return new ForEachBean("Harry");
}

// other factory methods
}

В этом примере мы указываем, что bean-компонент с именем «John» будет внедрен в список с именем «CollectionsBean» . Результаты, которые мы тестируем здесь:

ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class);
CollectionsBean collectionsBean = context.getBean(CollectionsBean.class);
collectionsBean.printBeanList();

Из вывода мы видим, что наша коллекция имеет только один элемент:

[John]

6. Установка пустого списка в качестве значения по умолчанию

Мы можем установить значение по умолчанию для введенного свойства List как пустой список, используя статический метод Collections.emptyList() :

public class CollectionsBean {

@Value("${names.list:}#{T(java.util.Collections).emptyList()}")
private List<String> nameListWithDefaultValue;

public void printNameListWithDefaults() {
System.out.println(nameListWithDefaultValue);
}
}

Если мы запустим это с ключом «names.list», не инициализированным через файл свойств:

collectionsBean.printNameListWithDefaults();

На выходе мы получим пустой список:

[ ]

7. Резюме

С помощью этого руководства мы узнали, как внедрять различные типы коллекций Java с помощью среды Spring.

Мы также рассмотрели внедрение ссылочных типов и то, как их выбирать или упорядочивать внутри коллекции.

Как обычно, полный код доступен в проекте GitHub .