(1). 背景
在Spring中,我一直所用的配置文件为(properties/yaml),但是,我这边需要做到动态配置,需要用到JSON,所以研究了下SpringBoot源码,发现底层是支持的.
(2). SpringApplicationJsonEnvironmentPostProcessor
public class SpringApplicationJsonEnvironmentPostProcessor
// *******************************************************************
// 1. 实现Env后置处理
// *******************************************************************
implements EnvironmentPostProcessor, Ordered {
public static final String SPRING_APPLICATION_JSON_PROPERTY = "spring.application.json";
public static final String SPRING_APPLICATION_JSON_ENVIRONMENT_VARIABLE = "SPRING_APPLICATION_JSON";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.stream().map(JsonPropertyValue::get).filter(Objects::nonNull)
// ******************************************************
// 只取第一个
// ******************************************************
.findFirst()
// ******************************************************
// 2. 对JSON进行处理:processJson
// ******************************************************
.ifPresent((v) -> processJson(environment, v));
} // end postProcessEnvironment
// ***********************************************************************
// 3. 通过JsonParser(Jackson)把JSON解析成Map
// ***********************************************************************
private void processJson(ConfigurableEnvironment environment, JsonPropertyValue propertyValue) {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> map = parser.parseMap(propertyValue.getJson());
if (!map.isEmpty()) {
// *******************************************************************
// 4. 交给:flatten处理
// *******************************************************************
addJsonPropertySource(environment, new JsonPropertySource(propertyValue, flatten(map)));
}
} // end processJson
private Map<String, Object> flatten(Map<String, Object> map) {
Map<String, Object> result = new LinkedHashMap<>();
flatten(null, result, map);
return result;
} // end flatten
private void flatten(String prefix, Map<String, Object> result, Map<String, Object> map) {
String namePrefix = (prefix != null) ? prefix + "." : "";
map.forEach((key, value) -> extract(namePrefix + key, result, value));
} // end flatten
@SuppressWarnings("unchecked")
private void extract(String name, Map<String, Object> result, Object value) {
if (value instanceof Map) {
if (CollectionUtils.isEmpty((Map<?, ?>) value)) {
result.put(name, value);
return;
}
flatten(name, result, (Map<String, Object>) value);
}
else if (value instanceof Collection) {
if (CollectionUtils.isEmpty((Collection<?>) value)) {
result.put(name, value);
return;
}
int index = 0;
for (Object object : (Collection<Object>) value) {
extract(name + "[" + index + "]", result, object);
index++;
}
}
else {
result.put(name, value);
}
} // end extract
}
(3). 总结
Spring的源码,值得我们去学习的,永远会开出一堆的接口,允许我们自由切换,以及组合使用.