Java 在Spring5.1.0中,在属性源之间加载和切换最优雅的方式是什么?

Java 在Spring5.1.0中,在属性源之间加载和切换最优雅的方式是什么?,java,spring,spring-boot,Java,Spring,Spring Boot,我希望在运行时加载和切换属性源,以读取不同的属性值,但在应用程序中使用相同的属性键 属性文件如下所示: A.财产 key1=ValueA1 key2=ValueA2 key1=ValueB1 key2=ValueB2 currency=R currency=$ B.财产 key1=ValueA1 key2=ValueA2 key1=ValueB1 key2=ValueB2 currency=R currency=$ 根据他们的 我用以下方法解决了我的问题: @PropertySo

我希望在运行时加载和切换属性源,以读取不同的属性值,但在应用程序中使用相同的属性键

属性文件如下所示:

A.财产

key1=ValueA1
key2=ValueA2
key1=ValueB1
key2=ValueB2
currency=R
currency=$
B.财产

key1=ValueA1
key2=ValueA2
key1=ValueB1
key2=ValueB2
currency=R
currency=$
根据他们的

我用以下方法解决了我的问题:

@PropertySource(value = "classpath:MessageMappingA.properties", encoding = "UTF-8", name = "A")
@PropertySource(value = "classpath:MessageMappingB.properties", encoding = "UTF-8", name = "B")

这看起来很难看,我怀疑是否真的有必要将这些属性源存储在一个列表中,并使用addFirst对它们进行重新排序,以便设置源的最高优先级。使用.properties文件作为加载不是更好吗?有什么建议吗?

根据文档

执行的搜索是分层的。。。 默认情况下,系统属性优先于环境变量

要覆盖加载的属性,必须将要使用的属性设置为最高优先级。根据规范,要做到这一点,需要调用propertySources.addFirstnew MyPropertySource;方法的属性souce

现在回到你的例子

@PropertySource(value = "classpath:MessageMappingA.properties", encoding = "UTF-8", name = "A")
@PropertySource(value = "classpath:MessageMappingB.properties", encoding = "UTF-8", name = "B")
上面的代码将最后加载属性B,这意味着如果B中的属性具有相同的键,则将加载它们

MessageMappingA.properties

key1=ValueA1
key2=ValueA2
key1=ValueB1
key2=ValueB2
currency=R
currency=$
MessageMappingB.properties

key1=ValueA1
key2=ValueA2
key1=ValueB1
key2=ValueB2
currency=R
currency=$
在注入@Value${currency}时,MessageMappingB将优先,值将为$。 如果要使用MessageMappingA的属性注入/覆盖,必须以最高优先级将其加载到环境的属性源中

public void setA() throws IOException {
    EncodedResource encodedResource = new EncodedResource(new ClassPathResource("MessageMappingA.properties"));
    ResourcePropertySource resourcePropertySource = new ResourcePropertySource(encodedResource);

    MutablePropertySources propertySources = this.environment.getPropertySources();
    propertySources.addFirst(resourcePropertySource);
}

但有一个陷阱

bean的默认作用域是singleton。MessageMappingA.properties的属性不会被注入@Scopesingleton类型的bean中,因为一旦bean初始化,就会注入MessageMappingB属性。 您需要确保希望使用新属性值的bean在每次调用时都将其注入。即使使bean@Scopeprototype也可能无法工作,因为调用它的上游bean可能是@Scopesingleton


我建议使用environment.getPropertykey而不是@Value${the.key}来获取属性值,当运行时加载不同的属性源以覆盖属性时。

您可以尝试为每个application.properties文件创建一个配置文件,在创建jar时,您可以指定要使用的配置文件,spring将使用您在pom.xml中配置的相应application.properties文件。何时调用setA&挫折?我假设它是在程序运行时的某个地方?@Rentius2407是的,我为运行时构建了这些方法,以便在这些.properties文件之间进行切换。请澄清,您要求在应用程序运行时切换属性,对吗?因为配置文件设置发生在容器初始化之前,不适合这种情况,所以我认为配置文件设置不是一个好主意。