Как сделать, чтобы дефолтные настройки Spring стартера подтягивались из application.yml и могли быть переопределены в сервисе
Что проверяют
Знаете ли вы, как устроен собственный стартер Spring Boot и в каком порядке Spring собирает свойства из разных источников. Следом часто спрашивают, как сервису переопределить не только значение, но и целый бин из стартера.
Как отвечать
Ключевая мысль: application.yml внутри jar стартера ненадёжен. На classpath окажутся два файла с одинаковым именем, и Spring возьмёт один из них, обычно файл самого сервиса. Поэтому дефолты кладут туда, где их ничто случайно не затрёт:
- класс свойств:
@ConfigurationProperties(prefix = "my.starter")с начальными значениями полей. Для record и привязки через конструктор дефолт задаётся аннотацией@DefaultValue. Всё, что сервис укажет в своёмapplication.yml, перекроет эти значения; - автоконфигурация: класс с
@AutoConfigurationи@EnableConfigurationProperties(MyStarterProperties.class), прописанный вMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. Черезspring.factoriesавтоконфигурации в Boot 3 уже не регистрируются; - отдельный файл дефолтов: если настроек много и хочется держать их в YAML, стартер подключает свой файл через
EnvironmentPostProcessorв конец списка источников (addLast), то есть с самым низким приоритетом; - бины: объявляются с
@ConditionalOnMissingBean, тогда сервис создаёт свой бин того же типа, и стартер отступает.
Дальше приоритет стандартный: профильный application-prod.yml выше общего, переменные окружения и аргументы командной строки выше файлов. Для подсказок в IDE подключите spring-boot-configuration-processor, он сгенерирует метаданные свойств.
Где спотыкаются
Вешают @Component на класс свойств в стартере. Пакет стартера сервис обычно не сканирует, и бин просто не появится.
Кладут дефолты в application.yml стартера и удивляются, что они то работают, то нет, в зависимости от порядка jar на classpath.
Пишут профиль старым ключом spring.profiles: dev. С Boot 2.4 для этого служит spring.config.activate.on-profile, а старый ключ современный Boot отвергает при запуске.