Love life, love coding, wechat search [Architecture Technology column] pay attention to this place like sharing. This article architecture technology column has been included, there are a variety of JVM, multi-threading, source code video, information and technical articles waiting for you to take

**Spring Boot series **

Spring Boot series (1) : Start the SpringApplication

Spring Boot series (2) Configuration feature analysis

Spring Boot series (3) : the latest version of elegant shutdown details

Spring Boot series (4) : Log dynamic configuration details

An overview,

The current Spring Boot version: 2.3.4.RELEASE, the speed of the update is also rapid, with the RELEASE of the new version, the company has also been upgraded step by step for the basic components of the upgrade, one of the most important part is the configuration file update (although currently all using Apollo). A comb through the configuration files for the new version of Spring Boot did find some previously unnoticed points.

Second, the new external configuration

1. Load the basic configuration

Spring Boot provides many external configuration parameters. You can use YAML files (you can also use properties, but it is not recommended), environment variables, and command-line parameters to distinguish between different environment configurations.

There are two ways to use the configuration:

  • Use the @value annotation to inject attributes contained in the Environment
  • Use @ConfigurationProperties to define a property class that contains the required properties (which can be configured in YAML).

There are so many external Spring Boot configurations. Which one will take effect?

Spring Boot loads the configuration in the following order, from high priority to low priority (the same configuration with high priority overwrites low priority), and from outside to inside:

1) Developer global configuration properties file (spring-boot-devtools.properties under $HOME/.config/spring-boot when developer tool is activated)

2) The test configured the @testpropertysource (“base. Properties “) annotation to load the configuration, such as base

3) The properties of @Springboottest are used in the test

4) Command line parameter configuration, which is used behind java-jar

5) SON configurations that can be loaded using the SPRING_APPLICATION_JSON property can be loaded in two ways:

  • SPRING_APPLICATION_JSON='{“persion”:{“name”:” XXX “}}’. This loading will add this data to the Spring Environment. We can get a property of persion. A value of XXX
  • Json ='{“persion”:{“name”:” XXX “}}’ -jar app.jar, Json property value is loaded as a String and is not parsed.

6) ServletConfig initialization configuration

7) ServletContext initialization configuration

8) Java: JNDI features of comp/env

9) Java System properties, which are obtained by System.getProperties()

10) Environment variables configured by the operating system

11) in RandomValuePropertySource configuration at random. Leading properties

12) Apply externally configured application-{profile}. Properties or YAML, you can use spring.profiles. Active to select the configured environment, If not selected, the default is application-default.properties. We can use spring.config.location to define the file’s path for loading.

13) Application -{profile}. Properties or YAML configured in your app, which is also used for multi-environment loading options, can be activated with spring.profiles. Active

14) Apply externally configured application.properties or YAML

15) Application -{profile}. Properties or YAML for the internal application configuration.

Here the SpringApplication of 14, and 15 will load the configuration properties from Application.properties.

This configuration overwrites the load from four locations in order of priority, with higher priority overwriting lower priority. Take a look:

  • Properties or application.yml in the /config folder of the current directory outside the application
  • Properties or application.yml in the current directory outside the application
  • Apply /config in the internal classpath, i.e. Application.properties or application.yml in resources/config
  • Application.properties or application.yml in the resources directory of the in-app classpath

16) The @Configuration class is configured with the @propertysource annotation, but this Configuration will not be loaded into the Environment until the Spring context refreshes. This loading method does not configure properties that need to be loaded before the application context is refreshed, such as logging.* and Spring.main.*.

Usage:

 / / here to load the classpath: / com/myco/app. The properties files
@Configuration
 @PropertySource("classpath:/com/myco/app.properties")
 public class AppConfig {

     @Autowired
     Environment env;

     @Bean
     public TestBean testBean(a) {
         TestBean testBean = new TestBean();
         testBean.setName(env.getProperty("testbean.name"));
         returntestBean; }}Copy the code

17) SpringApplication. SetDefaultProperties set of parameters

Here’s a Demo:

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}
Copy the code
  • You can configure name= laowang using application.yml in classpath
  • You can override the previous configuration by setting name = laoli using an external application.yml.
  • Jar –name=”Spring” to override the previous configuration.

Spring Boot configuration files also support wildcard loading. For example, you can use wildcard to load multiple files when using spring.config.additional-location and spring.config.location to load configurations.

2. Configure random attributes

Random properties of the injection is done by RandomValuePropertySource, it can help us to generate the integers, longs, uuid, strings of random values. This is very useful for us to do some test cases at ordinary times.

// Can be configured in application.yml
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024.65536]}
Copy the code

3. Command line properties

Port =9000. We can add the command line parameter server.port to our Environment using java-jar –server.port=9000. Normally, attributes added from the command line are of higher priority than ours.

If you don’t want to add the command line attribute to the application of the Environment, then you can configure SpringApplication. SetAddCommandLineProperties (false).

In fact, the most loaded property using the command line is probably the JavaAgent property, which is essential for APM monitoring in today’s companies. We can also use the command parameters to temporarily load some properties for testing.

4. The application loads the configuration file

In fact, I’ve already said that, and I’m going to mention it again. SpringApplication loads property configurations from Application.yml and adds them to Spring’s Environment for us to use. The priority is as follows, and the higher priority overwrites the lower priority:

  1. A /config subdirectory of the current directory
  2. The current directory
  3. A classpath /config package
  4. The classpath root

If you don’t like the configuration file called application.properties, you can also use spring.config.name. You can also use spring.config.location to specify the configuration load path.

For example:

// Modify my configuration file called myProject
java -jar myproject.jar --spring.config.name=myproject
  
  
// Load my config file somewhere else
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

Copy the code

Because the spring.config.name and spring.config.location configurations are used to determine which properties the application needs to load, they need to be loaded as early as possible. Generally, system environment variables, system parameters, and command line loading are used.

The default configuration loading path is as follows, and the installation priority is in descending order (file:./config/ has the highest priority). Therefore, you must pay attention when using the loading path:

  1. file:./config/
  2. file:./config/*/
  3. file:./
  4. classpath:/config/
  5. classpath:/

5. Use of placeholders

In application.properties we can use placeholders to dynamically load properties

For example, maven profiles can be used to dynamically replace environment parameters (such as mysql, redis, etc.) at packaging time.

A few examples:

// Simple to use
app.name=MyApp
app.description=${app.name} is a Spring Boot application
  
// Add --port=9000 instead of --server.port=9000 in the configuration file
server.port=${port:8080}


Copy the code

Note one thing:

If your POM is spring-boot-starter-parent, the default maven-resources-plugins will use @maven.token@ instead of ${maven.token}. This is done to prevent conflicts with Spring placeholders, so if we use Maven profiles or something else to dynamically replace the properties inside application.properties, use @name@.

6. YAML file for multi-environment configuration

1) Use of configuration files

In application.yml, you can use Spring.profiles to activate the environment configuration content you want to load.

Example:

server:
    address: 192.1681.100.
---
spring:
    profiles: development
server:
    address: 127.0. 01.
---
spring:
    profiles: production & eu-central
server:
    address: 192.1681.120.
Copy the code

In the example above, if we activate Development then server.address is 127.0.0.1. If production & EU-Central is enabled, server.address is 192.168.1.120. If I have none of these enabled, then server.address is 192.168.1.100 and the environment configuration is used directly to isolate.

Note: The spring.profiles property can be either a name or an expression.

2) use @profile annotations

We often encounter dynamic component selection issues, such as I have multiple access permissions or selective activation of data sources. But I don’t want to go back and forth and write if else, so @profile is a magic tool that makes our code more flexible.

For example, let’s rewrite a configuration belonging to the source:

/ / the first
@Configuration
@Profile("development")
public class StandaloneDataConfig {

    @Bean
    public DataSource dataSource(a) {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql") .build(); }}/ / the second
@Configuration
@Profile("production")
public class JndiDataConfig {

    @Bean(destroyMethod="")
    public DataSource dataSource(a) throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); }}Copy the code

In this way, we can activate different logic according to different configurations, and it would be even more beautiful to have a remote configuration center.

7. YAML problems

1) YAML has many advantages, but it certainly has a few minor drawbacks. By default, YAML files cannot be configured to load using the @propertysource annotation. If you don’t want to make unnecessary changes, just create a properties file.

2) Configuring multiple environment configurations in YAML can sometimes cause some strange problems, such as the following:

application-dev.yml

server:
  port: 8000
---
spring:
  profiles: ! "" test"
  security:
    user:
      password: "secret"
Copy the code

If I had loaded –spring.profiles. Active =dev when I started the application at this point, I would normally get security.user.password = secret, but this is not the case.

Because we used xxx-dev.yml on the configuration file name, the application-dev.yml file will be directly found when the application is loaded. At this point, the multi-environment configuration in our configuration file becomes invalid.

Yml, xxX-dev. yml, xxx-pro.yml, or multiple environments in one file. You can only choose one or the other to avoid the disgusting problem.

8. Object property binding

Sometimes we’ll have a set of properties of the same type that need to be loaded, and it’s really tiring to use @Value. Spring Boot provides us with a convenient way to use a single class for uniform configuration loading of the required variables.

Here’s an example:

/ / attribute class
package com.example;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("acme")
public class AcmeProperties {

    private boolean enabled;

    private InetAddress remoteAddress;

    private final Security security = new Security();

    public boolean isEnabled(a) {... }public void setEnabled(boolean enabled) {... }public InetAddress getRemoteAddress(a) {... }public void setRemoteAddress(InetAddress remoteAddress) {... }public Security getSecurity(a) {... }public static class Security {

        private String username;

        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

        public String getUsername(a) {... }public void setUsername(String username) {... }public String getPassword(a) {... }public void setPassword(String password) {... }public List<String> getRoles(a) {... }public void setRoles(List<String> roles) {... }}}Copy the code

At this point I configure the following properties in application.yml, and Spring Boot will help us bind the properties directly to the AcmeProperties class

acme.enabled =false

acme.remote-address=127.0.0.1

acme.security.username=xxx
Copy the code

Because @ EnableConfigurationProperties just help us to declare, in actual use we need to cooperate with * * * * @ Configuration, such as the Configuration below, so we can use @ the Resource Configuration after injected to attribute.

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {}Copy the code

Loose binding rules

The @ConfigurationProperties feature helps us bind object properties, but Spring Boot provides fairly loose binding rules.

For example, context-path is bound to the contextPath property, and PORT is bound to the PORT property, so let’s do a Demo.

@ConfigurationProperties(prefix="acme.my-project.person")
public class OwnerProperties {

    private String firstName;

    public String getFirstName(a) {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName; }}Copy the code

For example, we can bind a property to the firstName parameter in all four of the following configurations in application.yml, not too bad.

acme.my-project.person.first-name

acme.myProject.person.firstName

acme.my_project.person.first_name

ACME_MYPROJECT_PERSON_FIRSTNAME

Of course, in order to avoid problems, it is recommended to use lowercase attribute declaration such as acme.my-project.person.first-name.

10. Property binding verification

To the @ConfigurationProperties declared property class, we can add **@Validated** to verify the ConfigurationProperties.

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

    @NotNull
    private InetAddress remoteAddress;

    @Valid
    private final Security security = new Security();

    // ... getters and setters

    public static class Security {

        @NotEmpty
        public String username;

        // ... getters and setters}}Copy the code

Love life, love coding, wechat search [Architecture Technology column] pay attention to this place like sharing. This article architecture technology column has been included, there are a variety of JVM, multi-threading, source code video, information and technical articles waiting for you to take