背景
在Spring中,使用${user.name}的形式,能够自动从配置文件中读取user.name的值进行替换。包括AutowiredAnnotationBeanPostProcessor提供的@Value的注入功能。
原理
PropertyResolver
该接口的作用是解析属性值,提供了一系列获取属性以及解析属性的方法。
其中resolvePlaceholders(String text)和resolveRequiredPlaceholders(String text)提供了解析占位符${}属性解析的功能。

从继承图可以看出,我们熟知的StandardEnvironment也是一个PropertyResolver,在其父类AbstractEnvironment的方法:
private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);
private final ConfigurablePropertyResolver propertyResolver =
new PropertySourcesPropertyResolver(this.propertySources);
@Override
public String resolvePlaceholders(String text) {
return this.propertyResolver.resolvePlaceholders(text);
}
可以看出解析的动作交给了propertyResolver来进行,它是一个ConfigurablePropertyResolver,从继承图同样可以看出是一个PropertyResolver,且其内部持有了一个PropertySources,AbstractEnvironment默认提供了一个Log并使用组合对象MutablePropertySources来持有多个PropertySources,在构造函数中可以调用子类复写的customizePropertySources来添加额外的PropertySources
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
PropertySources
持有key/value属性值对,提供根据name获取value的功能
解析流程
在PropertyResolver解析占位符时,会创建一个占位符辅助器PropertyPlaceholderHelper
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
if (this.strictHelper == null) {
this.strictHelper = createPlaceholderHelper(false);
}
return doResolvePlaceholders(text, this.strictHelper);
}
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix,
this.valueSeparator, ignoreUnresolvablePlaceholders);
}
PropertyPlaceholderHelper持有占位符的前缀${,后缀},值分隔符:信息,用于将${user.name:123}解析出属性名user.name以及默认值123,然后从PropertySources中获取user.name对应的属性值,如果没有就使用默认值。
总结
PropertySources是资源信息,也是我们的配置属性
PropertyResolver是解析器,用于执行解析的动作。
PropertyPlaceholderHelper是占位符解析器,用于确认占位符字段,方便提取具体的属性名和默认值