有没有办法覆盖Spring Boot的PropertySourcesPropertyResolver并扩展Externalize configuration通过添加额外的属性源?
我想做的是在当前列表中添加另一个属性源,并能够使用当前机制覆盖该属性。 并扩展PropertySourcesPropertyResolver,因此当Spring映射用@ConfigurationProperties注释的类的属性时 请求 key 时,它可以检查具有两个不同前缀的 key 。
例如,如果我有来自两个不同位置的属性:
位置 1 的属性: data.user=用户名
位置 2 的属性: service.data.user=服务用户名
我希望能够使用 service.data.user 的值覆盖 data.user 的值(如果该属性存在)。
最佳答案
只是为了与他人分享,也许有人会觉得这很有用。
整个解决方案与扩展 PropertySourcesPlaceholderConfigurer 的 bean 相关。
- 部分是将另一个属性源添加到现有属性源列表中。 就我而言,我需要 application.property ,它存储在某个 jar 文件中。
为此,我们有 JarPropertiesPropertySource:
public class JarPropertiesPropertySource extends MapPropertySource implements Logger {
@SuppressWarnings({"unchecked", "rawtypes"})
public JarPropertiesPropertySource(String name, Properties source) {
super(name, (Map) source);
}
protected JarPropertiesPropertySource(String name, Map<String, Object> source) {
super(name, source);
}
}
主要逻辑位于 CustomPropertySourcesPlaceholderConfigurer bean 中:
public class CustomPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer implements Logger {
@Override
public PropertySources getAppliedPropertySources() throws IllegalStateException {
final MutablePropertySources mps = new MutablePropertySources();
// Get existing PropertySources
PropertySources ps = super.getAppliedPropertySources();
ps.forEach(propSource -> mps.addLast(new PropertySourceProxy(propSource)));
// Add JAR property source
mps.addLast(new JarPropertiesPropertySource("jar", ....))
return mps;
}
}
- 我们需要支持属性键重载。例如,如果我们有属性“serviceA|data.user”,并且该属性不存在,则尝试查找属性“data/user”。 为此,我们需要代理属性源,并且 super.getAppliedPropertySources() 中的每个属性都包装在代理 PropertySourceProxy 中。因此,每次 spring 对 getProperty 的调用都将通过代理方法并检查变化:
.
public class PropertySourceProxy extends PropertySource {
public PropertySourceProxy(PropertySource propertySource) {
super(propertySource.getName(), propertySource.getSource());
Object o = propertySource.getSource();
if (o instanceof StandardEnvironment) {
ConfigurableEnvironment ce = (ConfigurableEnvironment) o;
MutablePropertySources cemps = ce.getPropertySources();
cemps.forEach(propSource -> {
cemps.replace(propSource.getName(), new PropertySourceProxy(propSource));
});
}
}
@Override
public Object getProperty(String name) {
Object value = null;
if (name != null) {
int index = name.indexOf("|");
if (index != -1) {
String newName = name.substring(index + 1);
value = super.getProperty(newName);
}
}
if (value == null)
value = super.getProperty(name);
return value;
}
}
关于java - 如何重写 PropertySourcesPropertyResolver 并向外部化配置添加额外的属性源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29867969/