Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Группа настроек в записи

Аннотация @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.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.