- apollo主要功能就是获取配置,动态更新配置,spring内部配置存在Environment里,所以Environment是apollo接入spring的关键点之一
Environment主要用途:
- 配置存储:从各种数据源(PropertySource)获取配置,每个配置以KV的形式存在Environment,数据源包括配置文件、环境变量、系统变量等等
- Profiles切换:Environment还支持多Profiles,根据Profiles加载配置、Bean
- 处理占位符:替换配置里的占位符
Environment的使用:
- Environment对象默认已经初始化在IOC容器里,但是直接使用Environment对象的场景并不多,@Value和@ConfigurationProperties间接用来获取数据的场景的比较多
- Environment除了默认数据源还可以添加自定义数据源和配置!这个就是apollo操作的重点之一
Environment相关补充:
- Environment加载数据源在prepareEnvironment阶段,初始化spring context之前
- 处理@Value在BeanFactoryPostProcessor阶段,找到所有@Value标记的变量,从Environment找出配置替换掉,手动操作Environment可以实现apollo放入远程配置
- @ConfigurationProperties同样,只是@ConfigurationProperties是通过bean的形式获取Environment的配置
-
下面是一个environment样例,其中三个标记的数据源分别是系统参数、application.properties、自定义的配置文件,排序越靠前的获取优先级越高
- 替换配置源demo:
/**
* 替换environment里的数据,environment可以通过EnvironmentAware等等方式直接获取
* @param propertySource 数据源的名字
* @param key 替换的key
* @param newValue 替换的新值
*/
public void replaceProperties(String propertySource, String key, String newValue){
// environment的配置源集合里有系统变量、配置文件等等
MutablePropertySources propertySources = environment.getPropertySources();
if(propertySources.contains(propertySource)){
// 获取目标数据源
PropertySource<?> bootstrapPropertySource = propertySources.get(propertySource);
// 创建新的propertySource覆盖掉老的propertySource
Object source = bootstrapPropertySource.getSource();
if (source instanceof Map) {
// 删除旧的
propertySources.remove(propertySource);
Map<String, Object> externalProperties = new HashMap<>((Map<String, Object>) source);
externalProperties.put(key, newValue);
MapPropertySource newPropertySource = new MapPropertySource(propertySource, externalProperties);
// 添加新的数据源到优先级最高的位置
propertySources.addFirst(newPropertySource);
}
}
}
public void print(String key) throws BeansException {
// 使用environment获取配置
System.out.println("Environment-----" + environment.getProperty(key));
}