SpringBoot advanced - third-party bean property binding

1. Basic binding

1. @ConfigurationProperties annotation

The @ConfigurationProperties annotation is used to bind the member properties in the bean to the properties in the configuration file

Can be annotated on a class or method

custom bean

Just annotate @Component and @ConfigurationProperties on the class

For example, the yaml configuration file has the following configuration:

test-bean:
  ipaddress: 127.0.0.1
  port: 8080

There are the following TestBean:

@Data
@Component
@ConfigurationProperties(prefix = "test-bean")
// @ConfigurationProperties("test-bean")	// 默认即为 prefix 属性指定
public class TestBean {
    
    
    private String ipAddress;
    private int    port;
}

The prefix attribute of the @ConfigurationProperties annotation is used to specify the properties in the binding configuration

You can get the bean after getting the applicationContext in the startup class to see the effect:

@SpringBootApplication
public class Application {
    
    
    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
        TestBean bean = applicationContext.getBean(TestBean.class);
        System.out.println(bean);
        // 输出:TestBean(ipAddress=192.168.100.100, port=8088)
    }
}

Solve the error

In idea, the custom bean annotation @ConfigurationProperties may have the following errors

insert image description hereDoes not affect program operation

If you don’t want to see it, you can introduce the following dependencies to solve it

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

third-party beans

Write a method to return the bean in the configuration class, and annotate @Bean and @ConfigurationProperties on the method

Take DruidDataSource in Druid connection pool as an example

Pay attention to importing druid dependencies instead of druid-spring-boot-starter

The yaml configuration is as follows:

datasource:
  driver-class-name: com.mysql.cj.jdbc.Driver

We test the startup class as a configuration class:

@SpringBootApplication
public class Application {
    
    
    @Bean
    @ConfigurationProperties(prefix = "datasource")
    public DruidDataSource druidDataSource() {
    
    
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("noting");
        return dataSource;
    }

    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);

        DruidDataSource dataSource = applicationContext.getBean(DruidDataSource.class);
        System.out.println(dataSource.getDriverClassName());
		// 输出:com.mysql.cj.jdbc.Driver
    }
}

Note that the attribute set in the @Bean method will not affect the configuration in the configuration file

As in the above example, the setDriverClassName method is called in the method, but the output is still the attribute value in the yaml configuration

The value given by the set method in the @Bean method can be regarded as the default configuration, and the value in the yaml file is the final configuration

2. @EnableConfigurationProperties 注解

@EnableConfigurationProperties is annotated on the configuration class or startup class to specify the class that enables the binding, and multiple classes use an array

Its effect is the same as the annotation @Component on the bean, but both cannot take effect on one bean at the same time, and an error will be reported because two identical beans are found

Classes added by @EnableConfigurationProperties must be annotated with @ConfigurationProperties

@EnableConfigurationProperties will not be associated with @Bean annotated methods

The TestBean example is as follows:

@Data
//@Component
@ConfigurationProperties(prefix = "test-bean")
public class TestBean {
    
    
    // ...
}

Startup class:

@SpringBootApplication
@EnableConfigurationProperties({
    
    TestBean.class})
public class Application {
    
    
    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
        TestBean bean = applicationContext.getBean(TestBean.class);
        System.out.println(bean);
    }
}

2. Loose binding

Loose binding (or loose binding), which means that the binding property does not have to be strictly consistent with the property name

In the @ConfigurationProperties annotation, you can add any dash "-", but it cannot start with a dash and cannot contain uppercase letters. In fact, only lowercase letters and dashes can be used

In the yaml configuration file, any dash "-", underscore "_" and space can be added to the attribute name, which will not affect the matching of the binding

Example below:

TestBean:

@Component
@ConfigurationProperties(prefix = "test-bean")	// 可添加任意的 '-',但不可符号开头,也不可含大写字母
@Data
public class TestBean {
    
    
    private String ipAddress;	// 变量名也可添加 '_'
}

yaml:

# 以下均可正常匹配
testbean:
  ip-address: 192.168.0.101		# 烤肉串格式(官方推荐)
  ip_address: 192.168.0.102		# 下划线格式
  IP_ADDRESS: 192.168.0.103 	# 常量格式,大写与下划线
  "ip address": 192.168.0.104 	# 空格或双引号也是可以的
  -_iPa_d d-- Re ss: 192.168.0.105 	# 乱七八糟,只要字母可匹配就能生效

The officially recommended format is the kebab format. If there are multiple matching attributes, only the kebab format will take effect

In addition, according to Mr. Dark Horse Li, when @Value injects attribute values, loose matching is not supported

But it is ok when I personally test, the test class is as follows:

@SpringBootTest
class ApplicationTests {
    
    

    @Value("${mytest.message}")
    private String message;

    @Test
    void contextLoads() {
    
    
        System.out.println(message);
        // 输出:Hello world!!
    }
}

The yaml file is as follows:

my-test:
  _MESSAGE-: Hello world!!

As long as there are no symbols other than dashes and lowercase letters in @Value

3. Commonly used units of measurement

Duration means a period of time, such as 3 minutes, 5 hours

DataSize indicates the file size, such as 10B, 5MB

Such properties can specify units when configuring

as follows:

@Component
@ConfigurationProperties(prefix = "test-bean")
@Data
public class TestBean {
    
    
	// 指定默认时间单位,未设置则为毫秒 ms
    @DurationUnit(ChronoUnit.SECONDS)
    private Duration serverTimeout;
	// 指定文件单位,未设置则为字节 B
    @DataSizeUnit(DataUnit.KILOBYTES)
    private DataSize dataSize;
}

yaml configuration file:

test-bean:
  server-timeout: 3ms	#只支持天以内的单位:ms, s, m, h, d
  data-size: 10B		#必须大写:B, KB, MB, GB, TB

4. Attribute verification

For example, the setting range of the port number is 0 ~ 65535, we hope to verify the configuration at startup

  1. Introduce two dependencies of validation-api and hibernate-validator

validation-api provides the interface, and hibernate-validator provides the implementation

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>
  1. Annotate @Validated on the bean
  2. Annotation validation rules on attributes

Examples are as follows:

@Data
@Component
@Validated
@ConfigurationProperties(prefix = "test-bean")
public class TestBean {
    
    

    @Max(value = 65535, message = "最大端口号为 65535")
    @Min(value = 0, message = "最小端口号为 0")
    private int port;

}

There are other rules that can be customized in the javax.validation.constraints package, you can study it yourself

insert image description here

5. Hexadecimal Conversion Rules

Configuring pure numbers in the yaml file may lead to unexpected results, as shown in the following example:

yaml configuration:

my-test:
  password: 012345

Test class:

@SpringBootTest
class ApplicationTests {
    
    

    @Value("${my-test.password}")
    private String password;

    @Test
    void contextLoads() {
    
    
        System.out.println(password);
        // 输出:5349
    }
}

It can be found that the value of password is configured as 012345, but it turns out to be 5349

This is because 012345 triggers the octal conversion format

0 and so the number is less than 8, it will be converted to decimal as octal, and then injected into the attribute

Also, 0b starts with binary, and 0x starts with hexadecimal

Such as 0b_0101_0101 and 0x3f3f3f3f

It is recommended that the attributes of the string type be enclosed in double quotes, especially for passwords that are difficult to troubleshoot.

Supongo que te gusta

Origin blog.csdn.net/Cey_Tao/article/details/127584000
Recomendado
Clasificación