Several methods of reading externalized configuration by Spring boot

Posted by RobertPaul on Mon, 07 Feb 2022 07:57:11 +0100

In this article, we mainly discuss the externalized configuration function of Spring Boot. This function mainly realizes the mutual cooperation with the code through external configuration resources, so as to avoid hard coding and provide the flexibility of application data or behavior changes. This paper mainly records several common operation modes of reading externalized configuration, and the relevant principles are not recorded here.

1. Properties / YAML

We usually write the relevant configuration information in the Properties / YAML file, and then obtain the data in some way.

For example, in the following figure, I have defined three parameters:

1.1 Environment

First, we can load external configuration information through the Environment (all external configurations in Spring Boot will be loaded into the Environment).

First, we inject the Environment directly through Autowired:

@Autowired
Environment environment;

Then directly obtain the data information.

@RestController
public class ConfigController {

    @Autowired
    Environment environment;

    @GetMapping("/env")
    public String env() {
        return environment.getProperty("name") + "\n";
    }
}

1.2 notes

The second method is our commonly used annotation method, which directly writes the corresponding KEY through the annotation to obtain the corresponding value. If there is no KEY value, an error will be reported when starting.

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

2. Custom Properties file

Sometimes our external configuration may not be written in application Properties, but in some custom properties. At this time, how can we obtain the data through the value annotation?

When talking about the environment above, we know that all externalized configurations in spring boot will be loaded into the environment. We can modify it before spring boot builds the environment.

We can modify the environment by implementing the EnvironmentPostProcessor interface and overriding the postProcessEnvironment method.

The overall process is as follows:

  • Implement interface and rewrite method
  • Define the Properties and the name of the data file we need to get.
  • Parse the file and add the data to the environment
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private final Properties properties = new Properties();

    private String propertiesFile = "custom.properties";

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Resource resource = new ClassPathResource(propertiesFile);
        environment.getPropertySources().addLast(loadProperties(resource));
    }

    private PropertySource<?> loadProperties(Resource resource) {
        if (!resource.exists()) {
            throw new RuntimeException("file not exist");
        }
        try {
            //custom.properties
            properties.load(resource.getInputStream());
            return new PropertiesPropertySource(resource.getFilename(), properties);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

At this time, after the code is written, can we get the data through the value annotation? Let's run it. (remember to clear the data in application.properties)

At this time, we will find that the operation fails and the corresponding key is not found. Why? This is because the above is our expansion of Spring boot function. When expanding this function, we need to use our SPI mechanism to define our expansion implementation according to the expansion rules. Only in this way can our expansion point take effect.

This is different from the implementation of SPI mechanism in JAVA. Before SPI, the full class name file is created, and then the corresponding implementation class is written. The file name here needs to be defined as spring factories.

org.springframework.boot.env.EnvironmentPostProcessor=\
  com.example.springbootzookeeper.CustomEnvironmentPostProcessor

At this time, when we re run the project, we can find that it runs successfully.

3. Other command parameters

In Spring boot, there are many ways to externalize configuration, such as environment variables, system variables, command line parameters, etc. We demonstrate a type of externalized configuration below: we can externalize the configuration in this -d form. The key after the value annotation corresponds to the key after - D.

@Value("${test}")
private String command;

Topics: Spring Spring Boot