Я запускаю приложение с SpringBoot 2.1.1.RELEASE.
У меня есть файл yml со списком элементов, настроенных в профиле по умолчанию, а также в «локальном» профиле.
listOfSimpleObjects:
one: oneOne, oneTwo
three: nzerjpeojr
listOfObjects:
- id: idOne
name: nameOne
---
spring:
profiles: local
listOfSimpleObjects:
two: twoOne,twoTwo
listOfObjects:
- id: idTwo
name: nameTwo
Я хочу сопоставить эту конфигурацию с файлом свойств, определение которого
@ConfigurationProperties
public class MyProperties {
private Map<String, List<String>> listOfSimpleObjects = new HashMap<String, List<String>>();
private List<SubConfig> listOfObjects = new ArrayList<>();
public Map<String, List<String>> getListOfSimpleObjects() {
return listOfSimpleObjects;
}
public void setListOfSimpleObjects(Map<String, List<String>> listOfSimpleObjects) {
this.listOfSimpleObjects = listOfSimpleObjects;
}
public List<SubConfig> getListOfObjects() {
return listOfObjects;
}
public void setListOfObjects(List<SubConfig> listOfObjects) {
this.listOfObjects = listOfObjects;
}
}
public class SubConfig {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Работая с профилем "local", я ожидал получить объект Мои свойства с тремя элементами в списокпростыхобъектов и двумя в списокобъектов, но это не так.
Ниже тест Junit, который говорит мне, что в списокобъектов есть только один элемент.
@RunWith(SpringRunner.class)
@ActiveProfiles("local")
@SpringBootTest
public class MyPropertiesTest {
@Autowired
private MyProperties props;
@Test
public void testOnListOfStrings() {
// this assertion is ok :)
assertThat(props.getListOfSimpleObjects()).hasSize(3);
}
@Test
public void testOnListOfObjects() {
// this assertion fails :(
assertThat(props.getListOfObjects()).hasSize(2);
}
}
Я спросил своего коллегу, что все дело в ключах элементов, поскольку файл yml сначала представлен в большом HashMap.
Так что я думаю, что нет реального ответа на вопрос, который я мог бы задать, но в любом случае:
Спасибо за любой ответ :)
is there any way to have a merge version of the listOfObject ?
Из коробки нет, как указано в документация:
When lists are configured in more than one place, overriding works by replacing the entire list.
О :
Could SpringBoot be enhanced in order to support such feature (ie incase of detection of a list of items the merge is possible)
Вы можете открыть вопрос/запрос на Весенняя загрузка Git.
И вы догадались, что это работает для Map, как говорится в документе:
For Map properties, you can bind with property values drawn from multiple sources. However, for the same property in multiple sources, the one with the highest priority is used.
В качестве простого и ограниченного обходного пути (он работает только с одним конкретным профилем. С двумя у вас все равно будет проблема переопределения), вы можете указать новое имя свойства для списка в yaml конкретного профиля.
Таким образом, у вас будет два списка, но это не имеет значения, так как, наконец, вы можете объединить их, когда бин будет полностью загружен из аннотированного метода @PostConstruct.
Образец :
private List<SubConfig> listOfObjects = new ArrayList<>();
private List<SubConfig> listOfObjectsFromProfile = new ArrayList<>();
//... getters and setters
@PostConstruct
public void mergeList() {
listOfObjects.addAll(listOfObjectsFromProfile);
}
блин ... большое спасибо за вашу первую ссылку. Я прочитал так много весенних документов, но пропустил этот. Я посмотрю, открою я запрос или нет...