I. Предыстория
предыдущий поствведена система@ValueЛучшие практики, в этой статье будет документирован еще один главный герой конфигурации экстернализации Springboot.@ConfigurationProperties.
2. Лучшие практики для @ConfigurationProperties
Многие компоненты Springboot можно использовать «из коробки» без настройки. например, введениеspring-boot-redis-starter, вы можете использовать локальный Redis. Причина, по которой может быть достигнута возможность нулевой конфигурации, заключается в том, что она зависит от@ConfigurationPropertiesСпособность.
2.1 Основное использование
@ConfigurationProperties может сделать нашу конфигурацию модульной. Таким образом удобно централизованно управлять при использовании и обслуживании, а конфигурация каждого модуля не будет влиять друг на друга. Мы также можем использовать @Value, Environment, параметры запуска и т. д., чтобы добиться этого. Но это явно неприменимо в сценарии модульной функции.
Основное использование @ConfigurationProperties заключается в следующем:
класс пользовательской конфигурации
/**
* @author sunliming11
* @date created in 2021/2/17
*/
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "my.plugin")
public class MyPluginProperties {
/**
* 是否开启
*/
private Boolean enabled;
/**
* 插件名称
*/
private String name;
/**
* 别名
*/
private List<String> alias;
/**
* map属性
*/
private Map<String, String> map;
/**
* obj
*/
private Security security;
@Data
@ToString
public static class Security {
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 角色列表
*/
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
}
}
импортный пакет jar
нужно представитьspring-boot-configuration-processorпакет, основная возможность пакета состоит в том, чтобы обеспечитьConfigurationMetadataAnnotationProcessorЭтот постпроцессор, его роль заключается в@ConfigurationPropertiesСоздайте файл [метаданные].
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
настроить
Перед настройкой давайте сначала соберем проект. Если это IDEA, нажмите 🔨 в правом верхнем углу:
После этого вы можете увидеть в каталоге компиляции:
На данный момент мы можем видеть соответствующие подсказки при настройке в файле конфигурации yml:
Полная конфигурация YAML выглядит следующим образом:
my:
plugin:
name: 插件名称
enabled: true
alias:
- 别名1
- 别名2
- 别名3
map:
"[key1]": value1
"[key2]": value2
"/key3": value3
security:
password: 12345
username: 用户名
roles:
- USER
- ADMIN
Если вы используете конфигурацию свойств, полная конфигурация выглядит следующим образом:
my.plugin.name=插件名称
my.plugin.enabled=true
my.plugin.alias[0]=别名1
my.plugin.alias[1]=别名2
my.plugin.alias[2]=别名3
my.plugin.map[key1]=value1
my.plugin.map[key2]=value2
my.plugin.map[key3]=value3
my.plugin.security.username=用户名
my.plugin.security.password=12345
my.plugin.security.roles[0]=ADMIN
my.plugin.security.roles[1]=USER
В приведенном выше примере показано, как передать@ConfigurationPropertiesдля настройки POJO, который может легко внедрять сложные типы свойств. но@ValueЭто требует использования трюков и приемов для реализации внедрения сложных типов.
2.2 relaxed binding
поддержка SpringBoot@ConfigurationPropertiesсвободные правила связывания. Напримерacme.myProject.person.firstNameКонфигурация этого свойства имеет тот же эффект, что и следующий.
acme.my-project.person.first-name=LEON
acme.my_project.person.first_name=LEON
ACME_MYPROJECT_PERSON_FIRSTNAME=LEON
...
Основываясь на принципе свободного связывания, вышеприведенная нотация в конечном итоге может быть проанализирована. То есть для того же слова просто удалите驼峰式、下划线(\_)、短横线(-)Простые буквы после правила в конечном итоге одинаковы (без учета регистра) и могут быть проанализированы.
2.3 Лучший способ активации
использовать@ConfigurationPropertiesАннотацию нельзя использовать напрямую, нам также необходимо активировать этот класс конфигурации. Если этот класс конфигурации не активирован, проект Springboot все еще можно запустить в обычном режиме, но класс конфигурации использовать нельзя.
активация@ConfigurationPropertiesЕсть много способов, в принципе класс конфигурации можно внедрить в контейнер, даже если он активирован. Исходя из этого принципа, существуют следующие способы активации:
2.3.1 @Component
@Component // 通过@Component并被容器scan到,可以注入到容器中。
@ConfigurationProperties(prefix = "my.plugin")
public class MyPluginProperties {
……
}
2.3.2 @Configuration
@Configuration
@ConfigurationProperties(prefix = "my.plugin")
public class MyPluginProperties {
……
}
2.3.3 @Bean
@Configuration
public class MyConfiguration {
@Bean
public MyPluginProperties myPluginProperties() {
return new MyPluginProperties();
}
}
2.3.4 @EnableConfigurationProperties
@Configuration
@EnableConfigurationProperties(MyPluginProperties.class)
public class MyConfiguration {
}
В комментариях к исходному коду@EnableConfigurationPropertiesфункция состоит в том, чтобы обеспечить@ConfigurationPropertiesслужба поддержки. Как это поддерживается? Определение класса в исходном коде имеет:@Import(EnableConfigurationPropertiesRegistrar.class), то есть говорят, что он поддерживается благодаря возможности @Import.EnableConfigurationPropertiesRegistrarДостигнутоImportBeanDefinitionRegistrar, так что вы можете вводить пользовательскиеBeanDefinition, исходный класс пользовательского bd здесь@EnableConfigurationPropertiesЗначение, указанное в аннотации. BD может быть сгенерирован BD естественным путем.
С таким количеством способов его использования, какой из них лучше? На самом деле нет ни хорошего, ни плохого. Но все же рекомендуется использовать@EnableConfigurationProperties, Особые люди делают особые вещи.
2.4 Что делать, если атрибут или значение атрибута не могут быть сопоставлены
Если настроены избыточные атрибуты, такие как еще одна конфигурация в приведенном выше примереmy.plugin.name1
my:
plugin:
name: 插件名称
name1: 多余的配置
По умолчанию проект запускается нормально. Если вы хотите, чтобы проект не запускался, вы можете настроитьignoreUnknownFields = false:
@ConfigurationProperties(prefix = "my.plugin", ignoreUnknownFields = false)
Если типы атрибутов не совпадают, запуск по умолчанию завершится ошибкой.Если вы не хотите ошибаться, вы можете настроитьignoreInvalidFields = true:
@ConfigurationProperties(prefix = "my.plugin", ignoreInvalidFields = true)
2.5 Проверка
Механизм проверки Spring основан на JSR303, и Spring также поддерживает@ConfigurationPropertiesСвойства класса конфигурации основаны на проверке JSR303. Способ его использования очень прост, а именно:
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "my.plugin", ignoreUnknownFields = false, ignoreInvalidFields = true)
@Validated //开启校验
public class MyPluginProperties {
/**
* 是否开启
*/
private Boolean enabled;
/**
* 插件名称
*/
@NotNull
@Size(min = 12, max = 16)
private String name;
/**
* 别名
*/
@NotNull
private List<String> alias;
/**
* map属性
*/
private Map<String, String> map;
/**
* obj
*/
private Security security;
открыть в классе@ValidatedВот и все. Затем используйте аннотации проверки, поддерживаемые обычным JSR303.
2.6 Принцип «нулевой конфигурации»
В springboot, как добиться конфигурации 0? такие как импортspring-boot-redis-starter, вы можете запустить проект без какой-либо настройки, подключиться к локальной базе данных Redis и использовать ее.
существует@ConfigurationPropertiesОн также опирается на аннотацию на основе:@EnableAutoConfiguration. Эта аннотация по-прежнему основана на@ImportСпособность можно увидеть в исходном коде:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) //委托给AutoConfigurationImportSelector
public @interface EnableAutoConfiguration {
……
}
Его полная ссылка выглядит следующим образом:
@EnableAutoConfiguration➡️
@Import➡️
@AutoConfigurationImportSelector➡️
AutoConfigurationImportSelector➡️
выполнитьselectImports()➡️
Внутренний вызовgetAutoConfigurationEntry()➡️
Внутренний вызовgetCandidateConfigurations➡️
org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames➡️
Внутренний вызовloadSpringFactories()
В этом методе мы видим:
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}
result = new HashMap<>();
try {
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
}
......
В исходном коде вы можете увидетьFACTORIES_RESOURCE_LOCATIONПостоянное значение:
То есть, если вы используете@EnableAutoConfigurationAnnotation, то Springboot просканирует все пути к пакетам в процессе запуска.META-INF/spring.factories, все классы в этом файле будут внедрены сканированием Spring.
настроить
Основываясь на вышеуказанных знаниях, запустите новый модуль для настройки конфигурации. Структура каталогов следующая:
@Data
@ConfigurationProperties(prefix = "my.plugin")
public class MyPluginProperties {
/**
* 插件名称
*/
private String name = "我的自定义插件";
/**
* 是否开启
*/
private Boolean enabled;
}
//****************************************
@EnableConfigurationProperties(MyPluginProperties.class)
public class MyPluginAutoConfiguration {
}
Файл spring.factories выглядит следующим образом:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.leon.myplugin.MyPluginAutoConfiguration
Затем используйте пакет maven и внедрите его в проект Springboot:
<dependency>
<groupId>com.leon</groupId>
<artifactId>spring-boot-starter-myplugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
После повторного импорта вы можете использовать его в файле yml:
4. Недостатки @ConfigurationProperties
@ConfigurationPropertiesОчень мощный, но есть одно место, где его нельзя сравнить@Value, то есть выражения SpringEL не поддерживаются. Об этом прямо сказано на официальном сайте. Но это не мешает@ConfigurationPropertiesСтаньте одной из самых важных базовых возможностей Springboot.
@ValueПринцип таков: перед инициализацией bean-компонента сначала выполняется внедрение зависимостей, в основном делегированноеAutowiredAnnotationBeanPostProcessorзавершается постпроцессором;
@ConfigurationPropertiesПринцип такой: на основе@Importспособность пройтиEnableConfigurationPropertiesRegistrarЧтобы добиться внедрения BeanDefinition класса конфигурации, а затем внедрения атрибутов.
Принципы реализации этих двух совершенно разные.
V. Резюме
Эта статья в основном о@ConfigurationPropertiesВ процессе также демонстрируются использование и принцип работы «Springboot», а также вариант использования и принцип работы нулевой конфигурации «Springboot». Наконец-то сравнил@ConfigurationPropertiesа также@Valueпринципиальная разница.