java - 如何重写 PropertySourcesPropertyResolver 并向外部化配置添加额外的属性源

标签 java spring spring-boot

有没有办法覆盖Spring Boot的PropertySourcesPropertyResolver并扩展Externalize configuration通过添加额外的属性源?

我想做的是在当前列表中添加另一个属性源,并能够使用当前机制覆盖该属性。 并扩展PropertySourcesPropertyResolver,因此当Spring映射用@ConfigurationProperties注释的类的属性时 请求 key 时,它可以检查具有两个不同前缀的 key 。

例如,如果我有来自两个不同位置的属性:

位置 1 的属性: data.user=用户名

位置 2 的属性: service.data.user=服务用户名

我希望能够使用 service.data.user 的值覆盖 data.user 的值(如果该属性存在)。

最佳答案

只是为了与他人分享,也许有人会觉得这很有用。

整个解决方案与扩展 PropertySourcesPlaceholderConfigurer 的 bean 相关。

  1. 部分是将另一个属性源添加到现有属性源列表中。 就我而言,我需要 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/

    相关文章:

    java - Java 6 是否支持 VB?

    java - jdbc:从 java.sql.Type 代码中获取 SQL 类型名称

    java - 开源 Java 报告框架

    java - 如何将GroupSequenceProvider级联到成员列表?

    没有 Spring Framework 的 Spring Cloud Contract 测试(启动)

    hibernate - 在 Spring Boot/Hibernate/JPA 中指定连接表的表名和字段名

    java - 获取nativeQuery with table join result list into JSONObject

    java - CLOB 到二进制流的转换

    java - Hibernate 的恶作剧——我只想要一个非托管副本

    java - 在 Spring Boot RabbitMQ 运行时创建队列/交换/绑定(bind)/监听器