The Apollo
configuration center was used in the previous project. After docking with the Apollo configuration center, the properties of the configuration center are It can be used in the program, so how is this implemented? When were the properties of the configuration center loaded into the program? So if we find out how this is implemented, can we load configuration properties
and encryption and decryption functions of configuration properties
from anywhere?
From the above figure, we know that our requirements are very simple, that is, the attributes we define need to be larger than the configuration file has a higher priority.
When we want to use configuration properties in Bean, then we The configuration properties must be put into Spring Environment before the Bean is instantiated. That is, our interface needs to be called before application context refreshed
, and EnvironmentPostProcessor
can exactly implement this function.
We know that there is a priority for obtaining properties in Spring.
For example, we have the following configuration properties username
├─application.properties │ >> username=huan ├─application-dev.properties │ >> username=huan.fu
So what is the value of username
at this time? Here is a picture from Apollo
to explain this problem.
Reference link: https://www.apolloconfig.com/#/zh/design/apollo-design
Spring has been added since version 3.1 ConfigurableEnvironment
and PropertySource
:
ConfigurableEnvironment
Spring’s ApplicationContext will contain an Environment (implementing the ConfigurableEnvironment interface)
ConfigurableEnvironment itself contains many PropertySource
PropertySource
Property Source
can be understood as many Key-Value attribute configurations
As can be seen from the schematic diagram above, key
appears at the very beginning The priority in PropertySource
is higher. In the above example, the value of username
in SpringBoot
is huan.fu
.
From the second stepGet the priority of the configuration attribute
It can be seen that the higher the PropertySource
is, the higher Execute it first, then for our configuration to take effect, it must be placed as early as possible.
As can be seen from the above figure, SpringBoot loads various configurations through EnvironmentPostProcessor
, and the specific implementation is ConfigDataEnvironmentPostProcessor
to achieve. Then we write an implementation class of EnvironmentPostProcessor
ourselves, then execute it after ConfigDataEnvironmentPostProcessor
, and add it to the first position in Environment
.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.6</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.huan.springcloud</groupId> <artifactId>springboot-extension-point</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-extension-point</name> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
vim application.properties
username=huan
Note:
1. If you find that there is no log output in the program, check whether is used slf4j
Output log. At this time, the log cannot be output because the log system has not been initialized. The solution is as follows:
SpringBoot版本 >= 2.4 可以参考上图中的使用 DeferredLogFactory 来输出日志 < 2.4 1、参考如下链接 https://stackoverflow.com/questions/42839798/how-to-log-errors-in-a-environmentpostprocessor-execution 2、核心代码: @Component public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor, ApplicationListener<ApplicationEvent> { private static final DeferredLog log = new DeferredLog(); @Override public void postProcessEnvironment( ConfigurableEnvironment env, SpringApplication app) { log.error("This should be printed"); } @Override public void onApplicationEvent(ApplicationEvent event) { log.replayTo(MyEnvironmentPostProcessor.class); } }
1. Create a new# under src/main/resources
##META-INF/spring.factoriesFile
org.springframework.boot.env.EnvironmentPostProcessor=\ com.huan.springcloud.extensionpoint.environmentpostprocessor.CustomEnvironmentPostProcessor5. Write a test class and output the defined username attribute Value
@Component public class PrintCustomizeEnvironmentProperty implements ApplicationRunner { private static final Logger log = LoggerFactory.getLogger(PrintCustomizeEnvironmentProperty.class); @Value("${username}") private String userName; @Override public void run(ApplicationArguments args) { log.info("获取到的 username 的属性值为: {}", userName); } }
3. Write custom properties and add the solution provided by in Spring Environment.
看看别的地方是否实现了 EnvironmentPostProcessor或ApplicationContextInitializer或BeanFactoryPostProcessor或BeanDefinitionRegistryPostProcessor等这些接口,在这个里面修改了 PropertySource的顺序。
理解 Spring 获取获取属性的顺序 参考 2、获取配置属性的优先级
如下代码初始化日志系统
org.springframework.boot.context.logging.LoggingApplicationListener
The above is the detailed content of How to use SpringBoot's EnvironmentPostProcessor. For more information, please follow other related articles on the PHP Chinese website!