Spring Boot environment configuration Envirnoment

In Srping Boot, after we use EnvironmentAware to inject the Environment object, we can obtain system parameters, command line parameters, file configuration and other information in the Environment.

How does Environment store and manage these values? What about variable conflicts? Can we extend the behavior of Environment? This article combines the initialization process of Environment when Spring Boot starts to understand the configuration method, priority, configuration source and extension method of Environment.

What does Environment in Spring refer to?

What is Environment in Spring? Before understanding Environment, we have to mention Property and Profile.

When we write a project, we often extract some configuration items, which are usually called attributes in Java, that is, Property, which is essentially a set of key-value pair configuration information. The advantage of using configuration items is that it is easy to modify, just modify the configuration file or command line parameters, and then restart it.

During the development process, most projects have multiple sets of configurations corresponding to multiple environments, generally speaking, there are development environments, test environments, and production environments. The "environment" here is called Profile. The program can read the value of Profile, and display different characteristics according to different Profiles. In fact, "environment" is also a "configuration" in essence, but this configuration is too important and special, so it is treated as a separate concept.

Environment = Property + Profile

In Spring Boot, the implementation class of Environment used by default is StandardServletEnvironment. We can understand how the Environment in Spring Boot is managed through its class diagram.

The PropertyResolver interface is responsible for obtaining the Property (obtaining the value through the key). The Environment inherits this interface and adds the content of the Profile. ConfigurablePropertyResolver inherits PropertyResolver, in order to solve the problem of data type conversion and ${…} expression parsing involved in the process of obtaining Property. On this basis, ConfigurableEnvironment adds the setting function of Profile. ConfigurableWebEnvironment extends web functionality to take a servlet context as a configuration source.

AbstractEnvironment, StandardEnvironment, and StandardServletEnvironment are all Spring's implementations of the above functions.

Where does configuration come from in Spring Boot?

Configuration in Spring Boot comes from different places, most commonly from application.properties, application.yaml, environment variables, and command line arguments. We can see various configuration methods in Spring Boot's official documentation.

The official gives a total of 14 configuration methods, and gives the priority of configuration. The higher the number, the higher the priority.

  • Configured by hardcoding (SpringApplication.setDefaultProperties).
  • Use the @PropertySource annotation to specify the configuration file on the Spring Boot configuration class.
  • Use a configuration file (eg application.properties file).
  • Random attributes configured via random.*.
  • Environment variables in the operating system.
  • Java's system properties, which can be obtained through System.getProperties().
  • JNDI properties in java:comp/env.
  • ServletContext initialization parameters (web environment)
  • ServletConfig initialization parameters (web environment)
  • The SPRING_APPLICATION_JSON property, which is stored as JSON in a system environment variable.
  • Command line parameters, similar to java -jar -Denv=DEV and the like.
  • The @SpringBootTest annotation is only used in tests.
  • @TestPropertySource annotation, used only in tests.
  • Configuration located under $HOME/.config/spring-boot when devtools is activated.

There are so many configuration methods, and the sources of configuration items are diverse, how to expose these configurations to users? One way is to expose all sources to users, who can obtain configuration from any configuration source. Another way is to let Spring manage these configuration sources, arrange priorities internally, and expose a unified get method externally, and users do not need to know the details. Spring apparently uses the latter.

Spring uses PropertySource to represent a configuration source. PropertySource has many subclasses, such as SystemEnvironmentPropertySource, PropertiesPropertySource and so on. Spring maintains these PropertySources in a list. When a user wants to obtain a configuration, Spring will traverse these configuration sources and determine whether there is a matching configuration in turn. The data in the configuration source list actually represents the priority.

Here's how Spring gets a Property from propertySources.

protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
  if (this.propertySources != null) {
    for (PropertySource<?> propertySource : this.propertySources) {

      Object value = propertySource.getProperty(key);
      if (value != null) {
        if (resolveNestedPlaceholders && value instanceof String) {
          value = resolveNestedPlaceholders((String) value);
        }
        logKeyFound(key, propertySource, value);
        return convertValueIfNecessary(value, targetValueType);
      }
    }
  }
  return null;
}

In summary, the Environment in Spring Boot maintains several PropertySources, that is, configuration sources, and all configurations come from these configuration sources.

Java obtains system parameters through System.getProperties()

java.version Java runtime environment version

java.vendor Java Runtime Environment Vendor

java.vendor.url URL of the Java vendor

java.home Java installation directory

java.vm.specification.version Java Virtual Machine Specification version

java.vm.specification.vendor Java Virtual Machine Specification Vendor

java.vm.specification.name Java virtual machine specification name

java.vm.version Java virtual machine implementation version

java.vm.vendor Java virtual machine implementation vendor

java.vm.name Java virtual machine implementation name

java.specification.version Java Runtime Environment specification version

java.specification.vendor Java Runtime Environment Specification Vendor

java.specification.name Java runtime environment specification name

java.class.version Java class format version number

java.class.path Java class path

java.library.path A list of paths searched when loading libraries

java.io.tmpdir default temporary file path

java.compiler The name of the JIT compiler to use

java.ext.dirs path to one or more extension directories

os.name the name of the operating system

os.arch The architecture of the operating system

os.version OS version

file.separator file separator ("/" on UNIX systems)

path.separator path separator (":" on UNIX systems)

line.separator line separator ("/n" on UNIX systems)

user.name User's account name

user.home user's home directory

user.dir the user's current working directory

Guess you like

Origin blog.csdn.net/qq_32907491/article/details/131758368