Группа настроек в записи
Аннотация @Value удобна для одной-двух настроек. Когда их больше, строки ${...} расползаются по коду, а опечатку в имени легко не заметить. Аннотация @ConfigurationProperties собирает все настройки с общей приставкой в один объект — обычно в запись (record).
Запись с настройками
// src/main/java/com/example/blog/BlogProperties.java
package com.example.blog;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
@ConfigurationProperties("blog")
public record BlogProperties(
String title,
@DefaultValue("10") int pageSize) {
}Приставка blog означает: компонент title возьмётся из blog.title, а pageSize — из blog.page-size. Spring сам сопоставляет pageSize в коде и page-size в файле. @DefaultValue задаёт значение, если настройки нет.
Значения в файле
# src/main/resources/application.yaml
blog:
title: Блог Анны и Олега
page-size: 20Число 20 Spring сам превратит в int. Так же он умеет разбирать списки, длительности вроде 30s и размеры вроде 10MB.
Регистрация
Чтобы Spring нашёл такие записи, добавьте к главному классу @ConfigurationPropertiesScan:
// src/main/java/com/example/blog/BlogApplication.java
package com.example.blog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@SpringBootApplication
@ConfigurationPropertiesScan
public class BlogApplication {
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}
}Теперь BlogProperties — обычный бин, его можно получить в конструкторе.
Использование
Ограничим длину списка статей настройкой page-size:
// src/main/java/com/example/blog/PostService.java
@Service
public class PostService {
private final PostRepository repository;
private final Clock clock;
private final BlogProperties properties;
public PostService(PostRepository repository, Clock clock, BlogProperties properties) {
this.repository = repository;
this.clock = clock;
this.properties = properties;
}
public List<Post> findAll() {
return repository.findAll().stream()
.sorted(Comparator.comparing(Post::id))
.limit(properties.pageSize())
.toList();
}
// create() — как в уроке о внедрении зависимостей
}Метод findAll() отдаёт статьи по порядку номеров, но не больше 20. Чтобы поменять число, достаточно правки в application.yaml или переменной окружения BLOG_PAGE_SIZE=5 — код трогать не нужно.
@Value или запись
| Когда | Что выбрать |
|---|---|
| Одна настройка в одном месте | @Value |
| Несколько связанных настроек | Запись с @ConfigurationProperties |
| Настройка нужна в разных классах | Запись: имя пишется один раз |
Частая ошибка
Если значение нельзя превратить в нужный тип, приложение не запустится и точно скажет, где проблема:
Failed to bind properties under 'blog.page-size' to int:
Property: blog.page-size
Value: "abc"
Origin: "blog.page-size" from property source "commandLineArgs"
Reason: failed to convert java.lang.String to @org.springframework.boot.context.properties.bind.DefaultValue int (caused by java.lang.NumberFormatException: For input string: "abc")Строка Origin показывает источник неверного значения — здесь аргумент командной строки --blog.page-size=abc.