Environment means environment in Chinese, it represents the environment information of the whole spring application runtime, it contains two key factors
- profiles
- properties
profiles
The concept of profiles is believed to be understood by everyone. The most common one is the solution that determines the different configuration contexts in the current spring container in different environments. For example, for the development environment, test environment, and production environment, build different application.properties configuration items. At this time, we can use the properties of profiles to determine the configuration items that take effect in the current spring application context.
In fact, profiles can be used to logically group the configuration of beans. In short, we can logically group different beans through profiles. This grouping has nothing to do with the definition of the bean itself. Whether it is xml or annotation, you can configure which profile group the bean belongs to.
When there are multiple profile groups, we can specify which profile takes effect. Of course, if not specified, spring will execute it according to the default profile. Let's demonstrate it with a code.
ProfileService
Create a normal class with the following code
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 and configure different profiles.
@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 methods
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));
}
}
The configuration can be activated in many ways, by default when applicationContext.getEnvironment().setActiveProfiles("prod");
is not added, it will be found that the bean is not loaded. Once added, which bean to load will be determined 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 activated. This property can be configured in system environment variables, JVM system properties, etc.
Note that the profile is not a single choice; multiple profiles may be activated at the same time, programmatically use the method setActiveProfiles(), which receives String array parameters, that is, multiple profile names
applicationContext.getEnvironment().setActiveProfiles("prod","dev");
If no profile configuration is activated, the default profile will be activated.
The default profile profile can be changed through the setDefaultProfiles method of the environment variable, or the declared spring.profiles.default property value
profilesSummary
To briefly summarize profiles, profiles can be used to logically group a group of beans. These logically grouped beans will be loaded according to the active profiles configured in the Environment context, that is, Environment can determine the currently activated profiles for profiles configuration. Which profile is configured.
- A profile is a logical grouping of bean definitions.
- This group, which is the profile, is given a name, which is the profile name.
- Only when a profile is in the active state, its corresponding logically grouped bean definitions will be registered in the container.
- Beans can be added to the profile through XML definition or annotation annotation.
- The role of the Environment for profiles is to specify which profiles are currently active by default.
Properties
The role of properties is to store properties, which can help us manage various configuration information. The source of this configuration can be a properties file, JVM properties, system environment variables, or a special Properties object.
Let's take a look at the Environment interface, which inherits PropertyResolver. This interface is related to the operation of properties, that is, we can set and get related properties through Environment.
public interface Environment extends PropertyResolver {
String[] getActiveProfiles();
String[] getDefaultProfiles();
/** @deprecated */
@Deprecated
boolean acceptsProfiles(String... var1);
boolean acceptsProfiles(Profiles var1);
}
At this point, we can briefly summarize the role of Environment. Environment provides different profile configurations, and PropertyResolver provides configuration operations. From this, we can know that the Spring container can obtain different configuration information according to different profiles, so as to achieve Handling of the runtime environment in the Spring container.
application of environment
In the spring boot application, modify the application.properties configuration
env=default
Create a Controller for testing
@RestController public class EnvironementController { @Autowired Environment environment; @GetMapping("/env") public String env(){ return environment.getProperty("env"); } }
Specify the profile attribute
In the previous content, we introduced the two concepts of profile and property, and now let's use them together to deepen our understanding of the two.
In spring boot applications, the default external 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 configure different environments
application-profile.properties
Which properties file the current spring boot application chooses to use as the context configuration depends on the currently active profile. Similarly, we can activate it in many ways, such as adding spring.profiles.active=dev
to application.properties, or adding this configuration to the JVM parameters to specify the effective configuration.
If not specified, the default configuration file is used. In short, if a configuration file is not explicitly activated, the application will load the properties in application-default.properties.
This function is very practical. In general, companies have several operating environments, such as development, testing, and production environments. In these environments, some configuration information is different, such as server addresses. Then we need to use the specified configuration information for different environments, which can be easily solved in this way.
Use of @Value annotation
In addition to the properties defined in the properties file, which can be obtained through the getProperty method of the environment, spring also provides the @Value annotation,
@RestController
public class EnvironementController {
@Value("${env}")
private String env;
@GetMapping("/env")
public String env(){
return env;
}
}
When the spring container loads a bean, when it finds that the bean has the @Value annotation, it can inject the property value from the Environment. If there is no such property in the Environment, an error will be reported.
Spring Environment principle design
Combined with what we have said before, let's speculate on the implementation principle of Environment.
Briefly demonstrate the configuration source in Environment
- @Value("${java.version}") Get System.getProperties, get system properties
- Configure the jvm parameters of the command,
-Denvtest=command
Based on the derivation of the existing content, we can draw the following diagram.
- The first part is the property definition, which can come from many places, such as application.properties, or system environment variables.
- Then specify the path or the specified range to load these configurations according to the agreed method and save them in memory.
- Finally, we can look up this value from the cache based on the specified key.
The following is a class diagram representing Environment, which clearly reflects the principle of Environment.
The core API of the above class diagram is described as follows
Environment interface, inherits PropertyResolver. PropertyResolver, which has two main functions.
- Obtain the corresponding
propertValue
property value (getProperty) through thepropertyName
property name. - Replace property placeholders in
${propertyName:defaultValue}
format with actual values (resolvePlaceholders).
- Obtain the corresponding
- 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 (internally holds the property source list List<PropertySource>) as the source of property values, traverses each PropertySource in order, and returns a non-null property value when obtained.
Among them, List<PropertySource> in PropertySourcesPropertyResolver represents the source of different property sources, and its class diagram is as follows, representing the storage for different data sources.
Copyright notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated. Reprint please indicate from Mic takes you to learn architecture!
If this article is helpful to you, please help to follow and like, your persistence is the driving force for my continuous creation. Welcome to follow the WeChat public account of the same name to get more technical dry goods!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。