拓展
后续 PropertySourcesPlaceholderConfigurer
PropertyPlaceholderConfigurer 类
类定义
public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport {
继承自 PlaceholderConfigurerSupport
变量
// 不检测系统变量
public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
// 如果指定配置不存在,则以系统变量为准
public static final int SYSTEM_PROPERTIES_MODE_FALLBACK = 1;
// 系统变量优先级高于指定变量
public static final int SYSTEM_PROPERTIES_MODE_OVERRIDE = 2;
private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
处理占位符
protected String resolvePlaceholder(String placeholder, Properties props, int systemPropertiesMode) {
String propVal = null;
//系统变量优先级高于指定变量
if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) {
// 直接以系统变量为准
propVal = resolveSystemProperty(placeholder);
}
// 如果配置值不存在,以指定配置为准
if (propVal == null) {
propVal = resolvePlaceholder(placeholder, props);
}
// 如果指定配置值不存在,处理系统配置值
if (propVal == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) {
propVal = resolveSystemProperty(placeholder);
}
return propVal;
}
获取指定配置
非常简单,直接从 props 中获取即可。
protected String resolvePlaceholder(String placeholder, Properties props) {
return props.getProperty(placeholder);
}
获取系统配置
protected String resolveSystemProperty(String key) {
try {
// 获取系统配置值
String value = System.getProperty(key);
// 如果值不存在,则获取系统环境变量。
if (value == null && this.searchSystemEnvironment) {
value = System.getenv(key);
}
return value;
} catch (Throwable ex) {
// 异常处理
}
}
执行配置替换处理
上面的方法是获取到对应的配置,然后就是执行对应占位符 ${}
的属性替换。
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
doProcessProperties(beanFactoryToProcess, valueResolver);
}
其中 PlaceholderResolvingStringValueResolver
实现如下:
private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
private final PropertyPlaceholderHelper helper;
private final PlaceholderResolver resolver;
public PlaceholderResolvingStringValueResolver(Properties props) {
this.helper = new PropertyPlaceholderHelper(
placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
this.resolver = new PropertyPlaceholderConfigurerResolver(props);
}
@Override
public String resolveStringValue(String strVal) throws BeansException {
String resolved = this.helper.replacePlaceholders(strVal, this.resolver);
if (trimValues) {
resolved = resolved.trim();
}
return (resolved.equals(nullValue) ? null : resolved);
}
}
核心作用:通过配置,获取占位符对应的字符串值。
PropertyPlaceholderConfigurerResolver
实现如下:
private class PropertyPlaceholderConfigurerResolver implements PlaceholderResolver {
private final Properties props;
private PropertyPlaceholderConfigurerResolver(Properties props) {
this.props = props;
}
@Override
public String resolvePlaceholder(String placeholderName) {
return PropertyPlaceholderConfigurer.this.resolvePlaceholder(placeholderName, props, systemPropertiesMode);
}
}
执行 bean 属性替换
这个实现实在父类中。
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
StringValueResolver valueResolver) {
// 获取对象值定义 visitor 类
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
// 获取相关的所有 bean 名称
String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
for (String curName : beanNames) {
// 避免解析自己的配置,导致配置找不到的场景
if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
try {
//TODO: 后续可以在这里,获取对应的 bean 属性信息,
// 执行属性替换
visitor.visitBeanDefinition(bd);
}
catch (Exception ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
}
}
}
// 解决别名问题
beanFactoryToProcess.resolveAliases(valueResolver);
// 解决内嵌值问题,比如注解属性
beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}