getEnvironment方法
createEnvironment()当中调用new StandardEnvironment()。
StandardEnvironment调用父类AbstractEnvironment构造方法,
AbstractEnvironment构造方法调用子类(StandardEnvironment)的customizePropertySources(this.propertySources);
customizePropertySources方法添加环境属性、系统变量
resolveRequiredPlaceholders方法
getEnvironment().resolveRequiredPlaceholders(path)调用到AbstractEnvironment的resolveRequiredPlaceholders方法
propertySources 就是 createEnvironment方法时 new StandardEnvironment() 上面调用customizePropertySources时往里面添加系统变量和环境变量
PropertySourcesPropertyResolver调用父类AbstractPropertyResolver的resolveRequiredPlaceholders方法
createPlaceholderHelper方法创建赋值给this.strictHelper
PropertyPlaceholderHelper
doResolvePlaceholders方法将配置文件中的占位符进行值的替换处理
PropertyPlaceholderHelper#replacePlaceholders
在上面,PlaceholderResolver placeholderResolver 入参是一个lambda表达式,具体实现在PlaceholderResolver的子类PropertySourcesPropertyResolver的getPropertyAsRawString方法
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
Assert.notNull(value, "'value' must not be null");
return parseStringValue(value, placeholderResolver, null);
}
/**
* 解析字符串中的占位符(例如 ${...})
*
* @param value 待解析的原始字符串
* @param placeholderResolver 占位符解析器(用于查找占位符对应的实际值)
* @param visitedPlaceholders 已访问的占位符集合(用于检测循环引用,可为 null)
* @return 解析后的字符串
*/
protected String parseStringValue(
String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
int startIndex = value.indexOf(this.placeholderPrefix);
if (startIndex == -1) {
return value;
}
StringBuilder result = new StringBuilder(value);
while (startIndex != -1) {
int endIndex = findPlaceholderEndIndex(result, startIndex);
if (endIndex != -1) {
// 从${username} 解析出 username
String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
String originalPlaceholder = placeholder;
if (visitedPlaceholders == null) {
visitedPlaceholders = new HashSet<>(4);
}
// 检测循环引用(如 ${a} 引用 ${b},${b} 又引用 ${a})
if (!visitedPlaceholders.add(originalPlaceholder)) {
throw new IllegalArgumentException(
"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
}
// Recursive invocation, parsing placeholders contained in the placeholder key.
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
// Now obtain the value for the fully resolved key...
// placeholderResolver: 即入参 this::getPropertyAsRawString, 调用PropertySourcesPropertyResolver.getPropertyAsRawString()
// 通过解析器获取占位符的实际值
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
if (propVal == null && this.valueSeparator != null) {
int separatorIndex = placeholder.indexOf(this.valueSeparator);
if (separatorIndex != -1) {
String actualPlaceholder = placeholder.substring(0, separatorIndex);
String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
if (propVal == null) {
propVal = defaultValue;
}
}
}
if (propVal != null) {
// Recursive invocation, parsing placeholders contained in the
// previously resolved placeholder value.
// 递归解析占位符 KEY 本身可能嵌套的占位符(例如解析 ${${inner}})
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
if (logger.isTraceEnabled()) {
logger.trace("Resolved placeholder '" + placeholder + "'");
}
startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
}
// 未开启 ignoreUnresolvablePlaceholders 时,遇到无法解析的占位符立即抛异常
else if (this.ignoreUnresolvablePlaceholders) {
// Proceed with unprocessed value.
startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
}
else {
throw new IllegalArgumentException("Could not resolve placeholder '" +
placeholder + "'" + " in value "" + value + """);
}
visitedPlaceholders.remove(originalPlaceholder);
}
else {
startIndex = -1;
}
}
return result.toString();
}
public class Test1 {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put("msg", "this is msg");
properties.put("userJueJin.msg", "msg:${msg}");
// 模仿AbstractEnvironment
MutablePropertySources propertySources = new MutablePropertySources();
ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
// 模仿StandardEnvironment
propertySources.addLast(new PropertiesPropertySource("test", properties));
// 简单取值
String msg = propertyResolver.getProperty("msg");
// 占位符解析
String result = propertyResolver.resolveRequiredPlaceholders("userJueJin.msg");
}
}