Spring framework enableconfigurationproperties что это

Обновлено: 05.07.2024

Использование аннотаций @Value ("$ ") для внедрения свойств конфигурации иногда может быть проблематичным, особенно когда вы используете несколько свойств или данные имеют иерархический характер. SpringBoot предоставляет еще один метод использования атрибутов для реализации строго типизированного элемента управления Bean и проверки конфигурации приложения.

Упомянутый выше метод - это класс, указанный в аннотации @ConfigurationProperties. Это означает большую безопасность, строгий контроль типов и проверку приложений.

Например, в приведенном выше классе обязательными являются следующие элементы управления типом и значения по умолчанию.

acme.enabled, значение по умолчанию - false. Тип - логический, по умолчанию - false.

acme.remote-address с типом, который может быть приведен из String. Тип - String, который можно преобразовать в InetAddress.

@ConfigurationProperties против @Value Сходства и различия

Внедрение свойств через @Value является основным свойством контейнера, но не обеспечивает безопасную конфигурацию типа. В следующей таблице показаны сходства и различия между ними.

Feature @ConfigurationProperties @Value
Расслабленный переплет (гибкий переплет) Yes No
Поддержка метаданных Yes No
Оценка SpEL (языковая поддержка SPEL) No Yes

Если вы определяете набор ключей конфигурации для своих собственных компонентов, рекомендуется обернуть эти конфигурации через POJO, аннотированный с помощью @ConfigurationProperties. Во-первых, динамическое связывание не поддерживается через @Value, а во-вторых, вы не можете получить среду в среде через @Value переменная.

На заметку для классов конфигурации

Свойства класса аннотации @ConfigurationProperties можно настроить с помощью файлов свойств, файлов YAML, свойств среды и т. Д. Это общедоступные API-интерфейсы, но это не означает, что методы получения / установки можно использовать напрямую. Основные причины следующие.

В качестве стандартного свойства javabean методы получения и установки являются обязательными, но в некоторых классах они могут быть отброшены. Такие как класс карты, класс коллекции, массив, потому что они могут быть изменены локально, например по индексу. Кроме того, если свойство является классом pojo и было создано его экземпляр, метод установки не требуется, но если вы хотите создать его экземпляр через конструктор по умолчанию во время процесса привязки, вам понадобится метод установки. Существуют также плагины, такие как Lombok, которые также вносят дополнительную сложность.

Наконец, проясните, что рассматриваются только стандартные свойства Java Bean, а привязка к статическим свойствам не поддерживается. Стандартное программирование важно .

Как пользоваться
метод первый

С помощью вышеуказанного метода в контейнер вводится bean-компонент с именем acme-com.example.AcmeProperties. Настоятельно рекомендуется, чтобы @ConfigurationProperties учитывала только среду и не внедряла другие bean-компоненты из контейнера.

Путь второй

Внедрить AcmeProperties непосредственно в контейнер в качестве компонента

Путь третий

Используйте его в аннотированном методе @Bean открытого типа, который можно использовать для привязки свойств к сторонним компонентам. Например, в файле конфигурации свойств есть следующие конфигурации:

С помощью описанного выше метода можно ввести источник данных Druid, прочитав конфигурацию атрибута.

Relaxed Binding гибкая привязка

Следующая конфигурация в файле конфигурации имеет такой же эффект

Property Source Simple List
Properties Files Camel case, kebab case, or underscore notation Standard list syntax using [ ] or comma-separated values
YAML Files Camel case, kebab case, or underscore notation Standard YAML list syntax or comma separated values
Environment Variables Upper case format with underscore as the delimiter. _ should not be used within a property name Numeric values surrounded by underscores, such as MY_ACME_1_OTHER = my.acme[1].other
System properties Camel case, kebab case, or underscore notation Standard list syntax using [ ] or comma-separated values

Для написания некоторых сложных атрибутов обратитесь к документу: Слияние сложных типов

Преобразование свойств

Окончательное преобразование строки в файле конфигурации в атрибут в соответствующем классе должно быть преобразованием типа. Spring Boot предоставил необходимый преобразователь. Если вам нужен преобразователь нестандартного типа, есть три способа:

  1. Определите компонент с именем convertService
  2. Редактор настраиваемых атрибутов (через CustomEditorConfigurer)
  3. Пользовательские преобразователи (через beans, отмеченные @ConfigurationPropertiesBinding)

Анализ исходного кода:

Когда легко ввести Bean типа OwnerProperties, метод initializeBean, наконец, будет запущен:

Стек вызовов выглядит следующим образом:

Введите метод инициализации bean-компонента:

Наконец, будет обработан постпроцессор, а ConfigurationPropertiesBindingPostProcessor отвечает за операции привязки свойств.

Используемый здесь преобразователь: BindConverter internal property conversionService






Из приведенного выше видно, что в конвертере внутри BindConverter есть два агента. Каждый агент просматривается, чтобы найти конвертер. Если конвертер может быть найден, выполняется преобразование. Первый найденный конвертер имеет наивысший приоритет, а последующие преобразования Устройство больше не работает.



Наконец, будет вызван класс анализа DataSize.


Прервите точку в классе Converter, и сюда войдут более поздние преобразования.

Конвертер (StringToDurationConverter), используемый в настоящее время, выглядит следующим образом:

Бин с настраиваемым именем службы преобразования




Как видно из приведенного выше, для преобразования используется настраиваемый конвертер.

Редактор настраиваемых атрибутов (через CustomEditorConfigurer)

Добавьте следующее определение bean-компонента в класс конфигурации





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

Пользовательские преобразователи (через beans, отмеченные @ConfigurationPropertiesBinding)

Сначала найдите вариант использования аннотации в исходном коде

Вы можете найти следующее использование, определенное в org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration

Видно, что StringOrNumberToMigrationVersionConverter реализует интерфейс GenericConverter.

Конвертер, определенный таким образом, имеет самый низкий приоритет, поэтому закомментируйте преобразователь или редактор атрибутов, определенный двумя способами.

@ConfigurationProperties Проверка валидации

Spring Boot attempts to validate @ConfigurationProperties classes whenever they are annotated
with Spring’s @Validated annotation. You can use JSR-303 javax.validation constraint
annotations directly on your configuration class. To do so, ensure that a compliant JSR-303
implementation is on your classpath and then add constraint annotations to your fields, as shown in
the following example:

Каждый раз, когда класс @ConfigurationProperties аннотируется аннотацией Spring @Validated, Spring Boot будет пытаться проверить его.

Вы можете напрямую использовать аннотации ограничений JSR-303 javax.validation в классе конфигурации. Для этого убедитесь, что у вас есть совместимая реализация JSR-303 в пути к классам, а затем добавьте в это поле комментарии ограничений, как показано в следующем примере:

You can also trigger validation by annotating the @Bean method that creates the configuration
properties with @Validated.

Вы также можете запустить проверку, создав методы @Bean для свойств конфигурации с помощью аннотаций @Validated.

To ensure that validation is always triggered for nested properties, even when no properties are found,
the associated field must be annotated with @Valid. The following example builds on the preceding
AcmeProperties example:

Чтобы гарантировать, что проверка всегда запускается для вложенных атрибутов, даже если атрибуты не найдены, связанные поля должны быть помечены @Valid. Следующий пример основан на предыдущем примере AcmeProperties:

You can also add a custom Spring Validator by creating a bean definition called
configurationPropertiesValidator. The @Bean method should be declared static. The configuration properties validator is created very early in the application’s lifecycle, and declaring the
@Bean method as static lets the bean be created without having to instantiate the @Configuration
class. Doing so avoids any problems that may be caused by early instantiation.

Настройте параметры в файле конфигурации

Изменить параметры файла конфигурации

медицинское обследование

Сначала увеличьте конфигурацию:

Резюме: Используя ConfigurationProperties, один тип свойств может извлекаться вместе и контролироваться с помощью свойств строгого типа, дополнительная проверка может выполняться с помощью логики проверки и гибких методов конфигурации свойств, таких как горб, подчеркивание и т. Д. Что касается класса, измененного ConfigurationProperties как Bean, постпроцессор ConfigurationPropertiesBindingPostProcessor используется для привязки свойств во время процесса создания экземпляра, который также включает преобразование свойств и проверку безопасности.

Настройка приложения с помощью @ConfigurationProperties , как альтернатива использованию @Value .

  • Настройка и изменение функционала приложения через application.properties с использованием ConfigurationProperties
  • Интеграция application.properties с IDE
  • Проверка значений настроек

Для создания настройки приложения с использованием ConfigurationProperties, можно начать с класса свойств. В нем собственно указаны свойства, компоненты системы которые хотим настраивать.

Тут я объявил два spring бина

В классе AppProperties я указал ссылку на некоторый доступный сервис приложения, его я буду менять в application.properties, у меня будет две его реализации и я буду подключать одну из них в application.properties.

image

Вот их реализация

Вот этого уже теперь достаточно что бы начать настраивать application.properties. Но всякий раз когда вносятся изменения в класс с ConfigurationProperties, надо сделать rebuild проекта, после чего в проекте появится файл
\target\classes\META-INF\spring-configuration-metadata.json . Собственно его IDE использует для редактирования в файле application.properties. Его структуру я укажу в ссылке в материалах. Этот файл будет создан на основе класса AppProperties. Если теперь открыть файл application.properties и начать вводить «demo», то среда начнет показывать доступные свойства

image

При попытке ввести неверный тип IDE сообщит

image

Даже если оставить как есть и попытаться стартовать приложение, то будет вполне внятная ошибка

image

Дополнительные метаданные, это только для удобства работы с application.properties в IDE, если это не надо, можно не делать. Для этого есть возможность указать в дополнительном файле подсказки (hints) и др. информацию для среды. Для этого скопирую созданный файл spring-configuration-metadata.json в \src\main\resources\META-INF\ и переименую его в
additional-spring-configuration-metadata.json . В этом файле меня будет интересовать только секция «hints»: []

В ней можно будет перечислить например допустимые значения для demo.vehicle


В поле «name» указано св-во «demo.vehicle», а в «values» список допустимых значений. Теперь если сделать rebuild проекта и перейти в файл application.properties, то при вводе demo.vehicle получу список допустимых значений

image

При вводе отличного от предложенного, но того же типа, редактор подсветит, но приложение в этом случае будет стартовать, так как это не строгое ограничение, а всего лишь подсказка.

image

Ранее в проекте я объявил два сервиса MyDemoService1 и MyDemoService2 оба они имплементируют интерфейс DemoService, теперь можно настроить чтобы application.properties были доступны только сервисы имплементирующие этот интерфейс и соответственно в AppProperties классе инициализировался выбранный. Для этого есть Providers их можно указать в additional-spring-configuration-metadata. Провайдеры есть нескольких типов их можно посмотреть в документации, я покажу пример для одного, — spring-bean-reference . Этот тип показывает имена доступных bean-компонентов в текущем проекте. Список ограничивается базовым классом или интерфейсом.

Пример Providers для DemoService:


После чего в application.properties для параметра demo.service будет доступен выбор двух сервисов, можно посмотреть их описание (description из определения).

image

Теперь удобно выбирать нужный сервис, менять функционал приложения. Есть один момент для объектных настроек, Spring надо немного помочь конвертировать строку которая указана в настройке, в объект. Для этого делается небольшой класс наследник от Converter.

На диаграмме классов проекта видно как эти сервисы отделены от основного приложения и доступны через AppProperties.

image

К полям класса AppProperties можно добавить проверки доступные в рамках JSR 303. Про это я писал здесь. Получится проверяемый, удобный файл конфигурации приложения.

Логотип-весна-ю

Поэтому мы хотим использовать конфигурацию почты в качестве примера. Файл конфигурации находится в отдельном файле, который называется mail.properties . Свойства должны быть названы с использованием правильного соглашения, чтобы их можно было правильно связать. Давайте посмотрим несколько примеров:

  • protocol и PROTOCOL будут привязаны к полю protocol боба
  • smtp-auth , smtp_auth , smtpAuth будет привязан к полю smtpAuth бина
  • smtp.auth будет привязан к … хм к smtp.auth полю бобов!

Spring Boot использует некоторые @ConfigurationProperties правила для привязки свойств к @ConfigurationProperties компонентам @ConfigurationProperties и поддерживает иерархическую структуру.

Итак, давайте создадим компонент @ConfigurationProperties :

@ConfigurationProperties (locations = "classpath:mail.properties" , ignoreUnknownFields = false , prefix = "mail" )

… Это должно быть создано из следующих свойств ( mail.properties ):

В приведенном выше примере мы аннотировали компонент с помощью @ConfigurationProperties чтобы Spring Boot мог привязать к нему свойства. ignoreUnknownFields = false указывает Spring Boot ignoreUnknownFields = false исключение, когда существуют свойства, которые не соответствуют объявленному полю в компоненте. Это очень удобно при разработке! prefix позволяет выбрать префикс имени свойств для привязки.

Обратите внимание, что сеттеры и геттеры должны создаваться в @ConfigurationProperties компоненте @ConfigurationProperties ! И в противоположность аннотации @Value это может принести некоторый дополнительный шум в код (особенно в простых случаях, на мой взгляд).

Хорошо, но мы хотим использовать свойства для настройки нашего приложения. Существует как минимум два способа создания @ConfigurationProperties . Мы можем использовать его вместе с @Configuration который предоставляет @Bean s, или мы можем использовать его отдельно и внедрить в @Configuration компонент @Configuration .

Вам также нужно перечислить классы свойств для регистрации в @EnableConfigurationProperties аннотация, как показано в следующем пример:

И дает этот код:

Но в самом следующем абзаце говорится:

Даже если предыдущая конфигурация создает обычный компонент для AcmeProperties, мы рекомендуем @ConfigurationProperties иметь дело только с окружающей средой и, в частности, не вводить другие бобы из контекста. Сказав это, @EnableConfigurationProperties аннотация также автоматически применяется к вашему проекту, так что любой существующий компонент, аннотированный @ConfigurationProperties, настроен из окружающей среды

Предполагать, что перечисление bean-компонента @ConfigurationProperties под аннотацией @EnableConfigurationProperties необязательно.

Так что это? Экспериментально я видел, что если я аннотирую bean-компонент с @ConfigurationProperties , ему вводятся свойства, как и ожидалось, без необходимости перечислять его в @EnableConfigurationProperties , но если это так, то зачем перечислять все, что имеет @ConfigurationProperties аннотация в @EnableConfigurationProperties , как показано в документации? Есть ли какая-то разница?

3 ответа

Как сказал М. Дейнм @EnableConfigurationProperties для обеспечения поддержки @ConfigurationProperties . Если вы посмотрите аннотацию Java Doc, вы увидите:

Например, допустим, у вас есть класс, в обязанности которого входит чтение и хранение информации из вашего application.yml / application.properties , необходимой для подключения к различным базам данных. Вы аннотируете это с помощью @ConfigurationProperties .

Затем, как правило, у вас есть @Configuration аннотированный класс, который предоставляет DataSource @Bean вашему приложению. Вы можете использовать @EnableConfigurationProperties , чтобы связать его с классом @ConfigurationProperties и соответственно инициировать источники данных.

Вот небольшой пример:

application.yml

Конфигурация источника данных

Конфигурация соединения с источником данных

Если мы посмотрим на код ниже:

@Configuration @EnableConfigurationProperties @ConfigurationProperties(prefix="ar1") public class ar1Settings

@Configuration говорит Spring, чтобы он воспринимал это как класс конфигурации и регистрировал его как Bean-компонент

@EnableConfigurationProperties говорит Spring, чтобы он воспринимал этот класс как получатель значений application.yml / properties

@ConfigurationProperties сообщает Spring, какой раздел представляет этот класс.

Насколько я понимаю, если вам не нужно указывать раздел файла свойств, @ConfigurationProperties можно опустить.

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

@ConfigurationProperties - используется для связывания класса с внешним файлом свойств. Очень мощный и должен использоваться для разделения классов бинов с помощью класса сущности конфигурации.

@Configuration - Создает bean-компонент Spring стереотипа конфигурации.

@EnableConfigurationProperties - создает привязку между классом объекта конфигурации и стереотипом конфигурации Spring, чтобы после внедрения в службу можно было легко получить свойства.

Читайте также: