一、简介
EnvironmentPostProcessor可以在spring conetxt refreshed之前,添加或者修改环境配置。
EnvironmentPostProcessor 在实现类必须在META-INF/spring.factories中注册
启动顺序控制方式:可以实现 Ordered 接口,或者可以在类上增加@Order注解.
EnvironmentPostProcessor接口实现代表:ConfigFileApplicationListener, 其他实现:CloudFoundryVcapEnvironmentPostProcessor, ConfigDataEnvironmentPostProcessor, DebugAgentEnvironmentPostProcessor, DevToolsHomePropertiesPostProcessor, DevToolsPropertyDefaultsPostProcessor, RandomValuePropertySourceEnvironmentPostProcessor, SpringApplicationJsonEnvironmentPostProcessor, SystemEnvironmentPropertySourceEnvironmentPostProcessor
使用场景:需要在应用启动前注入环境变量的
二、Environment
Environment是在spring应用中存储运行时的环境变量,提供了一些可以访问环境变量的方法,意味着我们可以动态去注入、修改、读取环境变量。Enviroment变量来自于bootstrap proterties、application properties、系统环境变量、jvm环境变理、servlet context parameters等。
三、实现原理
SpringApplication的run方法中在prepareEnvironment中调用 EventPublishingRunListener 中会调用environmentPrepared方法, 在environmentPrepared方法中会发布事件ApplicationEnvironmentPreparedEvent EnvironmentPostProcessorApplicationListener监听ApplicationEnvironmentPreparedEvent 事件,当environment prepared后执行自定义的EnvironmentPostProcessor
四、Example
通过以下示例,将会带大家实现一个Nacos的启动环境注入环境变量,主要目的是将nacos启动配置内置,将配置隔离机制也内置,实现0配置启动应用
4.1 实现自定义的 EnvironmentPostProcessor,在启动时将环境变量注入
public class WafNacosEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
private static final String CONFIG_PREFIX = "spring.cloud.nacos.config.";
private static final String DISCOVERY_PREFIX = "spring.cloud.nacos.discovery.";
private static final String KEY_CONFIG_SERVERADDR = CONFIG_PREFIX + "serverAddr";
private static final String KEY_CONFIG_USERNAME = CONFIG_PREFIX + "username";
private static final String KEY_CONFIG_PASSWORD = CONFIG_PREFIX + "password";
private static final String KEY_CONFIG_GROUP = CONFIG_PREFIX + "group";
private static final String KEY_CONFIG_FILEEXTENSION = CONFIG_PREFIX + "file-extension";
private static final String KEY_DISCOVERY_SERVERADDR = DISCOVERY_PREFIX + "serverAddr";
private static final String KEY_DISCOVERY_USERNAME = DISCOVERY_PREFIX + "username";
private static final String KEY_DISCOVERY_PASSWORD = DISCOVERY_PREFIX + "password";
private static final String KEY_DISCOVERY_NAMESPACE= DISCOVERY_PREFIX + "namespace";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Map<String, Object> map = new HashMap<>();
Properties envProperties = WafNacosConfig.getNacosConfig(getActiveEnv(environment));
//nacos config
addProperties(environment, map, KEY_CONFIG_SERVERADDR,envProperties.getProperty(SERVER_ADDR));
addProperties(environment, map, KEY_CONFIG_USERNAME,envProperties.getProperty(USERNAME));
addProperties(environment, map, KEY_CONFIG_PASSWORD,envProperties.getProperty(PASSWORD));
addProperties(environment, map, KEY_CONFIG_GROUP,getApplicationName(environment));
addProperties(environment, map, KEY_CONFIG_FILEEXTENSION,"yml");
//nacos discovery
addProperties(environment, map, KEY_DISCOVERY_SERVERADDR,envProperties.getProperty(SERVER_ADDR));
addProperties(environment, map, KEY_DISCOVERY_USERNAME,envProperties.getProperty(USERNAME));
addProperties(environment, map, KEY_DISCOVERY_PASSWORD,envProperties.getProperty(PASSWORD));
addProperties(environment, map, KEY_DISCOVERY_NAMESPACE,getApplicationName(environment));
if(!map.isEmpty()) {
environment.getPropertySources().addLast(new MapPropertySource("NacosBootstrap", map));
}
}
private void addProperties(ConfigurableEnvironment environment, Map<String, Object> map, String key, String value){
if(!environment.containsProperty(key)){
map.put(key, value);
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}