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

Внедрение массивов и списков из файлов свойств Spring

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

1. Обзор

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

2. Поведение по умолчанию

Начнем с простого файла application.properties :

arrayOfStrings=ForEach,dot,com

Давайте посмотрим, как Spring ведет себя, когда мы устанавливаем для нашей переменной тип String[] :

@Value("${arrayOfStrings}")
private String[] arrayOfStrings;
@Test
void whenContextIsInitialized_thenInjectedArrayContainsExpectedValues() {
assertArrayEquals(new String[] {"ForEach", "dot", "com"}, arrayOfStrings);
}

Мы видим, что Spring правильно предполагает, что наш разделитель — запятая, и соответствующим образом инициализирует массив.

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

3. Внедрение списков

Если мы попытаемся внедрить List таким же образом, мы получим неожиданный результат:

@Value("${arrayOfStrings}")
private List<String> unexpectedListOfStrings;
@Test
void whenContextIsInitialized_thenInjectedListContainsUnexpectedValues() {
assertEquals(Collections.singletonList("ForEach,dot,com"), unexpectedListOfStrings);
}

Наш список содержит один элемент, равный значению, которое мы установили в нашем файле свойств.

Чтобы правильно внедрить List , нам нужно использовать специальный синтаксис Spring Expression Language (SpEL):

@Value("#{'${arrayOfStrings}'.split(',')}")
private List<String> listOfStrings;
@Test
void whenContextIsInitialized_thenInjectedListContainsExpectedValues() {
assertEquals(Arrays.asList("ForEach", "dot", "com"), listOfStrings);
}

Мы видим, что наше выражение начинается с # вместо $ , к которому мы привыкли с @Value .

Следует также отметить, что мы вызываем метод разделения , что делает выражение немного более сложным, чем обычное внедрение.

Если мы хотим немного упростить наше выражение, мы можем объявить наше свойство в специальном формате:

listOfStrings={'ForEach','dot','com'}

Spring распознает этот формат, и мы сможем внедрить наш список , используя несколько более простое выражение:

@Value("#{${listOfStrings}}")
private List<String> listOfStringsV2;
@Test
void whenContextIsInitialized_thenInjectedListV2ContainsExpectedValues() {
assertEquals(Arrays.asList("ForEach", "dot", "com"), listOfStringsV2);
}

4. Использование пользовательских разделителей

Давайте создадим похожее свойство, но на этот раз мы будем использовать другой разделитель:

listOfStringsWithCustomDelimiter=ForEach;dot;com

Как мы видели при внедрении списков , мы можем использовать специальное выражение, в котором мы можем указать желаемый разделитель:

@Value("#{'${listOfStringsWithCustomDelimiter}'.split(';')}")
private List<String> listOfStringsWithCustomDelimiter;
@Test
void whenContextIsInitialized_thenInjectedListWithCustomDelimiterContainsExpectedValues() {
assertEquals(Arrays.asList("ForEach", "dot", "com"), listOfStringsWithCustomDelimiter);
}

5. Инъекция других типов

Рассмотрим следующие свойства:

listOfBooleans=false,false,true
listOfIntegers=1,2,3,4
listOfCharacters=a,b,c

Мы видим, что Spring поддерживает базовые типы «из коробки», поэтому нам не нужно выполнять какой-либо специальный синтаксический анализ:

@Value("#{'${listOfBooleans}'.split(',')}")
private List<Boolean> listOfBooleans;

@Value("#{'${listOfIntegers}'.split(',')}")
private List<Integer> listOfIntegers;

@Value("#{'${listOfCharacters}'.split(',')}")
private List<Character> listOfCharacters;
@Test
void whenContextIsInitialized_thenInjectedListOfBasicTypesContainsExpectedValues() {
assertEquals(Arrays.asList(false, false, true), listOfBooleans);
assertEquals(Arrays.asList(1, 2, 3, 4), listOfIntegers);
assertEquals(Arrays.asList('a', 'b', 'c'), listOfCharacters);
}

Это поддерживается только через SpEL, поэтому мы не можем внедрить массив таким же образом.

6. Программное чтение свойств

Чтобы читать свойства программно, нам сначала нужно получить экземпляр нашего объекта Environment :

@Autowired
private Environment environment;

Затем мы можем просто использовать метод getProperty для чтения любого свойства, указав его ключ и ожидаемый тип:

@Test
void whenReadingFromSpringEnvironment_thenPropertiesHaveExpectedValues() {
String[] arrayOfStrings = environment.getProperty("arrayOfStrings", String[].class);
List<String> listOfStrings = (List<String>)environment.getProperty("arrayOfStrings", List.class);

assertArrayEquals(new String[] {"ForEach", "dot", "com"}, arrayOfStrings);
assertEquals(Arrays.asList("ForEach", "dot", "com"), listOfStrings);
}

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

В этом кратком руководстве мы научились легко внедрять массивы и List с помощью быстрых и практических примеров.

Как всегда, код доступен на GitHub .