SpringBoot startup process: create Environment

Environment composition

First of all, Environment is an interface provided by Spring 3.1. It is an abstraction of the environment of the currently running application, let's take a look at its composition.
First look at the uml class diagram:

Environment consists of two parts

1)profiles

The Chinese literal translation of profile means "overview", "introduction", and "outline", but when using spring to develop applications, our understanding of profile is more intimate when it is used to divide multiple environments.

Usually, we will divide the profile into such as: development, test, pre-production, production environment. Each environment will have some bean s that are different, configured differently, etc. Each profile will have a corresponding bean and configuration to match it, so when we switch profiles, we will naturally switch the corresponding beans and configuration files, so as to achieve rapid switching in different environments and avoid the problem of constant modification.

This is the meaning of "logical group" described in spring's java doc.

2)properties

The concept of properties must be very familiar to us. In java, properties represent the key-value object collection of key-value. The properties in the Environment are different. It defines a name to represent the name of the file, and a generic source (which can be understood as a Map) is an object of a key-value structure to store the corresponding key value.
Below is the source code of PropertySource

public abstract class PropertySource<T> {

    protected final String name;

    protected final T source;

    // omit
}

It looks like a key-value data structure, right? Please pay attention here! Slightly different from what we imagined, for example

We created a config.properties file with content like

username=test
password=a123456

Then when the file config.properties is loaded into memory and exists as a PropertySource, name=config instead of name=username or password. That is to say, when loading resources such as config.properties, the generic T will be a Map collection, and the Map collection contains all the key-value pairs in the config.properties file.

Also, we notice that PropertySource is an abstract class. spring will use different implementations for different sources of resources. For example, in the above example, config.properties is loaded into memory and added as a Properties object, which is one of the implementation classes of PropertySource. PropertiesPropertySource.
To sum up, Environment contains profile s for switching environments, as well as properties for storing key-value pairs.

prepareEnvironment creates Environment

The main logic code for creating Environment

private ConfigurableEnvironment prepareEnvironment(
        SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments
        ) {
    // Create an Environment object
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // Configure the Environment object
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    // Trigger listeners (mainly trigger ConfigFileApplicationListener, which will load configuration files such as application.properties/yml)
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
                deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

The core content of the method consists of three parts

1) Create an Environment object

2) Configure the Environment object

3) Trigger the ConfigFileApplicationListener listener (loading application.properties/yml will be explained in subsequent articles)

getOrCreateEnvironment()
Let's follow up the getOrCreateEnvironment method to see the creation process

private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    }
    switch (this.webApplicationType) {
    case SERVLET:
        return new StandardServletEnvironment();
    case REACTIVE:
        return new StandardReactiveWebEnvironment();
    default:
        return new StandardEnvironment();
    }
}

In the first article, we mentioned that SpringApplication will infer the specific enumeration instance of WebApplicationType in the reduceFromClassPath method, which represents the type of the current application.

In the getOrCreateEnvironment method, the specific Environment type is selected according to the WebApplicationType type, that is, the Servlet type, the Reative type or the non-Web application type we mentioned.

configureEnvironment()

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    if (this.addConversionService) {
        ConversionService conversionService = ApplicationConversionService.getSharedInstance();
        environment.setConversionService((ConfigurableConversionService) conversionService);
    }
    // Add initial properties (note: properties such as application.properties/yml are not currently loaded)
    configurePropertySources(environment, args);
    // Add the initial profile (note: the configuration profile such as application.properties/yml is not currently loaded)
    configureProfiles(environment, args);
}

Summarize

So far, we have generally explained the interface design of Environment, the data structure design of profile and properties. From the prepareEnvironment method, we can see that the Environment is created after matching the webApplicationType. At this point, the brief introduction of Environment-related content is over, and we have also initially created an Environment object for the spring Context.

It is written in detail: https://www.cnblogs.com/lay2017/p/11483943.html

Tags: Spring

Posted by kingleo on Thu, 19 May 2022 09:39:09 +0300