Environment represents the environment information for the entire spring application runtime, which contains two key elements.

  • profiles
  • properties

profiles

The concept of profiles, which I believe we all understand, is most commonly used in different environments to determine different configuration contexts for solutions in the current spring container. For example, for the development environment, test environment, production environment, build different application.properties configuration items, this time we can determine the current spring application context in effect through the property profiles.

In fact, you can logically group the configurations of beans through profiles. Simply put, we can use profiles to logically group different beans, and this grouping has nothing to do with the definition of the bean itself, either in xml or annotated form, to configure which profile group the bean belongs to.

When there are multiple profile groups, we can specify which profile takes effect, but if not, spring will execute according to the default profile. Let’s demonstrate this with a code.

ProfileService

Create a normal class with the following code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class ProfileService {
    private String profile;

    public ProfileService(String profile) {

        this.profile = profile;
    }

    @Override
    public String toString() {
        return "ProfileService{" +
                "profile='" + profile + '\'' +
                '}';
    }
}

Declare a configuration class

In the configuration class, build two beans with different profiles configured.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@Configuration
public class ProfileConfiguration {

    @Bean
    @Profile("dev")
    public ProfileService profileServiceDev(){
        return new ProfileService("dev");
    }

    @Bean
    @Profile("prod")
    public ProfileService profileServiceProd(){
        return new ProfileService("prod");
    }
}

Define test method

1
2
3
4
5
6
7
8
9
public class ProfileMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
//        applicationContext.getEnvironment().setActiveProfiles("prod");
        applicationContext.register(ProfileConfiguration.class);
        applicationContext.refresh();
        System.out.println(applicationContext.getBean(ProfileService.class));
    }
}

There are many ways to activate the configuration. By default, when applicationContext.getEnvironment().setActiveProfiles("prod"); is not added, the bean will not be loaded. After it is added, it will decide which bean to load based on the currently active profiles.

In addition, we can also add -Dspring.profiles.active=prod to the startup parameters to determine which profile is currently active. this property can be configured in system environment variables, JVM system properties, etc.

Note that profiles are not optional; multiple profiles may be active at the same time, programmatically using the method setActiveProfiles(), which takes an array of String parameters, i.e. multiple profile names

1
applicationContext.getEnvironment().setActiveProfiles("prod","dev");

If no profile configuration is activated, the default profile will be activated. The default profile configuration file can be changed, either by the setDefaultProfiles method of the environment variable, or by the declared spring.profiles.default property value

Summary of profiles

A brief summary of profiles, through profiles can most a set of beans for logical grouping, these logical grouping of beans will be loaded according to the active profile configured in the context of the Environment, that is, the Environment for profiles configuration, it can determine which profile configuration is currently active.

  • A profile is a logical grouping of a set of bean definitions.
  • This grouping, that is, this profile, is given a name, that is, the profile name.
  • Only when a profile is active, its corresponding logically organized group of these bean definitions is registered to the container.
  • A bean can be added to a profile either by XML definition or annotation annotation.
  • The role that Environment plays for profiles is to specify which profiles are currently active by default.

Properties

The role of properties is to store properties, which help us manage various configuration information. The source of this configuration can be a properties file, JVM properties, system environment variables, or specialized Properties objects, etc.

Let’s take a look at the Environment interface, which inherits from PropertyResolver. This interface is related to the operation of properties, that is, we can set and get related properties through Environment.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public interface Environment extends PropertyResolver {
    String[] getActiveProfiles();

    String[] getDefaultProfiles();

    /** @deprecated */
    @Deprecated
    boolean acceptsProfiles(String... var1);

    boolean acceptsProfiles(Profiles var1);
}

So far, we can briefly summarize the role of Environment, Environment provides different profile configuration, and PropertyResolver provides the operation of the configuration, so we can know that Spring container can get different configuration information according to different profiles, so as to achieve the processing of the runtime environment in Spring container.

application of environment

  • In spring boot application, modify application.properties configuration

    1
    
    env=default
    
  • Create a Controller for testing

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    @RestController
    public class EnvironementController {
    
        @Autowired
        Environment environment;
    
        @GetMapping("/env")
        public String env(){
            return environment.getProperty("env");
        }
    }
    

Specifying profile properties

In the previous section we introduced the concepts of profile and properties, now let’s use them together to deepen our understanding of both.

In spring boot applications, the default externalized configuration is the application.properties file. In fact, in addition to this default configuration file, we can also use the convention naming format in springboot to achieve different environment configurations

1
application-profile.properties

The current spring boot application chooses which properties file to use as the contextual environment configuration, depending on which profile is currently active, and can be activated in a variety of ways, such as by adding spring.properties.active= dev This way, or you can add it to the JVM parameters to specify the active configuration.

In the case where it is not specified, the default configuration file is used. Simply put, if a configuration file is not explicitly activated, then the application will load the properties in application-default.properties.

This feature is very useful, generally there are several running environments inside the company, such as development, testing and production environments, there will be some configuration information in these environments are different, such as the server address. Then we need to use the specified configuration information for different environments, through this way can be very convenient to solve.

Use of @Value annotation

In addition to the properties defined in the properties file, which can be obtained through the environment’s getProperty method, spring also provides the @Value annotation that

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@RestController
public class EnvironementController {

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

    @GetMapping("/env")
    public String env(){
        return env;
    }
}

spring container in loading a bean, when found that the bean has @Value annotation, then it can inject the property value from the Environment, if the property is not in the Environment, then throw an exception.

Spring Environment principle design

Let’s speculate on the implementation principle of Environment in conjunction with what we have talked about earlier.

A simple demonstration of the configuration sources in Environment

  • @Value("${java.version}") Get System.getProperties , get system properties.
  • Configure the jvm parameter for command, -Denvtest=command.

Based on the derivation of the existing content, we can draw a diagram like the following.

Spring Environment

  • The first part is the property definition, which can come from many places, such as application.properties, or system environment variables, etc.
  • Then we specify the path or the range to load these configurations according to the convention and save them to memory.
  • Finally, we can look up this value from the cache based on the specified key.

This is the following class relationship diagram that represents Environment, this class relationship diagram is still very clear to reflect the principle of Environment.

Spring Environment

The core API of the above class diagram is described as follows

  1. Environment interface, which inherits from PropertyResolver. PropertyResolver, which has two main roles.
    • Get the corresponding propertValue property value (getProperty) by the propertyName property name.
    • Replace the property placeholders in the ${propertyName:defaultValue} format with the actual values (resolvePlaceholders).
  2. The concrete implementation class of PropertyResolver is PropertySourcesPropertyResolver, the solution for property sources. This class is the only complete implementation class in the system. It takes the PropertySources property source collection (which internally holds a list of property sources) as the source of property values, iterates through each PropertySource in order, and returns a non-null property value when it is obtained.

Among them, the List in PropertySourcesPropertyResolver, which represents the sources of different property sources, has the following class relationship diagram, which represents the storage for different data sources.

Spring Environment

Reference https://www.cnblogs.com/mic112/p/15917673.html