1 Introduction
Let's use an article earlier< [Spring] just want to record the use of @ Value in one article, and don't want to find any more (with mind map attached)>
It explains in detail how to use @ Value in Spring to meet our configuration requirements. It is powerful and easy to use. But it also has its limitations. For example, for the mail service, we have configured:
mail.hostname=smtp.qq.com mail.username=larry@qq.com mail.password=123456 mail.to=to@163.com mail.cc=cc@gmail.com
Using @ Value, we need 5 annotations and 5 independent variables:
@Value("${mail.hostname}") private String hostname; @Value("${mail.username}") private String username; @Value("${mail.password}") private String password; @Value("${mail.to}") private List<String> to; @Value("${mail.cc}") private List<String> cc;
This is very inconvenient, error prone, difficult to maintain and difficult to transfer. If the configuration of the same function can be combined, the configuration will not be so messy. Spring boot provides us with the annotation @ ConfigurationProperties to solve this problem perfectly. Now let's take a closer look at the power of this annotation.
2 three ways to start annotation
There are three ways to start @ ConfigurationProperties:
(1) Property class @ ConfigurationProperties + property class @ Component
@Component @ConfigurationProperties(prefix = "pkslow") public class PkslowProperties { private String name; private List<String> emails; private Map<String, Integer> price; //getter and setter }
There are three ways to annotate @ ConfigurationProperties on the property configuration class. The first way is to declare an available Bean through @ Component. In fact, it is not necessarily @ Component, @ Service and so on.
(2) Property class @ ConfigurationProperties + configuration class @ Bean
Declare in the configuration class through @ Bean:
@Configuration public class Config { @Bean public PkslowProperties pkslowProperties(){ return new PkslowProperties(); } }
(3) Property class @ ConfigurationProperties + configuration class @ EnableConfigurationProperties
We can add the annotation @ EnableConfigurationProperties to the Springboot startup class to declare:
@SpringBootApplication @EnableConfigurationProperties(PkslowProperties.class) public class ConfigurationPropertiesDemoApplication { public static void main(String[] args) { SpringApplication.run(ConfigurationPropertiesDemoApplication.class, args); } }
3 two advantages
3.1 loose binding rules
Loose binding rules are supported, and the following formats can be recognized as accountType properties:
pkslow.accountType=QQ pkslow.accounttype=QQ pkslow.account_type=QQ pkslow.account-type=QQ pkslow.ACCOUNT_TYPE=QQ
3.2 support multiple attribute types
Multiple attribute types are supported. Java classes are as follows:
@Component @ConfigurationProperties(prefix = "pkslow") @Data public class PkslowProperties { private String name; private List<String> emails; private Map<String, Integer> price; private Account mainAccount; private List<Account> emailAccounts; private Map<String, Account> friendAccounts; private Duration activeTime; private DataSize appFileSize; }
The configuration is as follows:
#Ordinary type pkslow.name=Larry #List pkslow.emails[0]=larry@qq.com pkslow.emails[1]=larry@gmail.com #Map pkslow.price.shoe=200 pkslow.price.pen=10 pkslow.price.book=43 #Object pkslow.mainAccount.username=larry pkslow.mainAccount.password=123456 pkslow.mainAccount.accountType=Main #List<Object> pkslow.emailAccounts[0].username=larry pkslow.emailAccounts[0].password=****** pkslow.emailAccounts[0].accounttype=QQ pkslow.emailAccounts[1].username=larry pkslow.emailAccounts[1].password=xxxxxx pkslow.emailAccounts[1].account_type=Gmail pkslow.emailAccounts[2].username=larry pkslow.emailAccounts[2].password=xxxxxx pkslow.emailAccounts[2].account-type=163 pkslow.emailAccounts[3].username=larry pkslow.emailAccounts[3].password=xxxxxx pkslow.emailAccounts[3].ACCOUNT_TYPE=Apple #Map<String, Object> pkslow.friendAccounts.JJ.username=JJ pkslow.friendAccounts.JJ.password=****** pkslow.friendAccounts.JJ.accountType=QQ pkslow.friendAccounts.Larry.username=Larry pkslow.friendAccounts.Larry.password=****** pkslow.friendAccounts.Larry.accountType=QQ #Duration pkslow.activeTime=30d #DataSize pkslow.appFileSize=10KB
Duration is a duration attribute. The supported units are:
-
ns: nanosecond
-
us: microsecond, microseconds
-
ms: millisecond, ms
-
s: Second, second
-
m: Minute, minute
-
h: Hour, hour
-
d: Day, day
Do not write the default is MS, or you can specify the unit by annotation @ DurationUnit.
@DurationUnit(ChronoUnit.DAYS) private Duration timeInDays;
Similar to DataSize, it is used to represent the file size. The supported units are: B/KB/MB/GB/TB. The default unit is B, which can be specified with @ DataSizeUnit.
4 attribute conversion failure handling
4.1 types that cannot be converted
Sometimes, if the configuration is wrong, it cannot be converted to a normal type. For example, if the property is a boolean type, but it is defined as pkslow.enabled=open, it cannot be converted. By default, it fails to start and throws an exception.
Description: Failed to bind properties under 'pkslow.enabled' to boolean: Property: pkslow.enabled Value: open Origin: class path resource [application.properties]:46:16 Reason: failed to convert java.lang.String to boolean Action: Update your application's configuration
But if we don't want to affect the startup of spring boot, we can set the ignoreInvalidFields property to true (the default is false), and the wrong property will be ignored.
@Component @ConfigurationProperties(prefix = "pkslow", ignoreInvalidFields = true) public class PkslowProperties { }
After setting, the wrong property will take the default value, such as null or false.
4.2 unknown properties
What happens if the wrong value is not the configured value, but the configured item?
#Java class does not have the property myAppName pkslow.myAppName=pkslow
Nothing will happen as a result.
Because by default, Springboot ignores the unrecognized fields. If you want it to fail to start in this case, you can configure ignore unknown fields to be false, which is true by default. In this way, you have to delete this misconfigured property.
@Component @ConfigurationProperties(prefix = "pkslow", ignoreUnknownFields = false) public class PkslowProperties { }
There are two points to note:
(1) If ignoreInvalidFields is set to true, ignoreUnknownFields will not work;
(2) Do not use the same prefix (namespace) for different classes with @ ConfigurationProperties. It is easy to cause conflicts. For example, one property is available and the other is unavailable.
5 custom converter
As explained earlier, Duration and DataSize are special properties. In fact, we can also customize the properties, and customize the converter to implement the property binding.
The configuration is as follows:
pkslow.convertAccount=Larry:123456:QQ
The corresponding properties are:
private Account convertAccount;
The Account class is as follows:
@Data @NoArgsConstructor @AllArgsConstructor public class Account { private String username; private String password; private String accountType; }
The Converter interface is implemented to customize the Converter as follows:
public class AccountConverter implements Converter<String, Account> { @Override public Account convert(String s) { String[] strings = s.split(":"); return new Account(strings[0], strings[1], strings[2]); } }
Enable the converter by annotating the @ ConfigurationPropertiesBinding declaration:
@Configuration public class Config { @Bean @ConfigurationPropertiesBinding public AccountConverter accountConverter() { return new AccountConverter(); } }
After that, you can use the custom properties and configuration.
6 use Spring Boot Configuration Processor
The custom attributes are alarmed in the IDE and cannot be recognized as legal configurations. This problem can be solved by introducing spring boot configuration processor, and IDE can also start auto completion function.
Introduce:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
6.1 completion of automatic completion
After introducing dependency, re build the project. It will create a Json file for us:
6.2 the tag configuration attribute is Deprecated
Put the annotation @ DeprecatedConfigurationProperty in the getter method, and the property will also be displayed as Deprecated:
@Component @ConfigurationProperties(prefix = "pkslow") public class PkslowProperties { private String name; @DeprecatedConfigurationProperty public String getName() { return name; } }
The effects of auto completion and Deprecated are as follows:
7 Summary
This article explains in detail the use of @ConfigurationProperties through code cases, and the code of demo can focus on the background Reply of public numbers "ConfigurationProperties".
Welcome to the public number "pumpkin slow talk", which will continue to update for you.
Read more, share more; write more, organize more.