Java Spring@ConfigurationProperties解析器忽略外部化属性

Java Spring@ConfigurationProperties解析器忽略外部化属性,java,spring,spring-boot,Java,Spring,Spring Boot,我使用@ImportResource({“classpath:property sources.xml”})注释将某些配置文件的路径外部化 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns

我使用
@ImportResource({“classpath:property sources.xml”})
注释将某些配置文件的路径外部化

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <util:properties id="externalProperties"
                     ignore-resource-not-found="true"
                     location="file:${dir.data}/foo.properties"
    />

    <context:property-placeholder ignore-unresolvable="true" properties-ref="externalProperties"/>
</beans>
application.yml(已由
@ConfigurationProperties
解析器成功处理)

应该没有区别。此外,bean本身没有什么特别之处:

@ConfigurationProperties(prefix = "descriptions", ignoreUnknownFields = false)
public class Descriptions {

    private Map<String, String> foo = new HashMap<>();

    public Map<String, String> getFoo() {
        return foo;
    }

    public void setFoo(Map<String, String> foo) {
        this.foo = foo;
    }
}
@ConfigurationProperties(prefix=“descriptions”,ignoreUnknownFields=false)
公共类描述{
私有映射foo=newhashmap();
公共地图getFoo(){
返回foo;
}
公共void setFoo(映射foo){
this.foo=foo;
}
}
为什么
@Value
始终有效,而
@ConfigurationProperties
仅适用于
应用程序。yml

注释可用于实现同样的效果

@Component
@PropertySource("classpath:foo.properties")
public class TestProperties {

    @Value("${descriptions.foo.bar.baz}")
    private String descriptions;

    //getters and setters

}
配置属性等效

    import org.springframework.boot.context.properties.ConfigurationProperties;

    @Configuration
    @PropertySource("classpath:foo.properties")
    @ConfigurationProperties
    public class TestProperties {

        private String descriptions;

        //getters and setters

    }
可以在属性文件中设置file.name的值:

file.name=yourpath
文件foo.properties提供了一个
properties
对象,该对象保存字符串=>字符串映射“descriptions.foo.bar.baz”=>“test”。字符串“descriptions.foo.bar.baz”通常不能转换为嵌套
Map
s这样的结构


另一方面,application.yml提供了与应用程序预期完全相同的结构,嵌套的
Map
s。因此,它之所以能够工作,是因为类型擦除:
void setFoo(Map foo)
需要一个
Map
。因此,当
foo.get(“bar”)
用作字符串时,应用程序将抛出ClassCastException,因为实际值将是一个映射。

在XML文件中,您正在将属性文件加载到
属性
对象中,然后将其传递给另外配置的
属性SourcePlaceHolderConfiguration
。这就是名称空间魔术所做的一切

propertySourcePlaceHolderConfigure
将使用这些属性解析
@value
或xml中的值表达式。它不会将加载的属性添加到
环境
环境
是Spring Boot中的
配置属性绑定后处理器
正在使用的环境。这也会在过程的早期运行

相反,您应该做的是将
@PropertySource
放在
@springbootcapplication
注释类上:

@PropertySource(value="file:${dir.data}/foo.properties", ignoreResourceNotFound=true)
或者使用
spring.config.additional location
属性指定要加载的其他配置文件

--spring.config.additional-location=file:${dir.data}/foo.properties

对于后者,您无需更改任何内容,只需指定在启动时加载哪些文件即可

您是否尝试过使用@SpringBootApplication和@PropertySource(value=“file:/pathtofile”)注释
@ConfigurationProperties
不是通过使用
PropertySourcePlaceHolderConfigure
来解析的,因此您在XML中的尝试没有帮助。将
@PropertySource(“file:${dir.data}/foo.properties”)
添加到
@SpringBootApplication
注释类中,以便将它们加载并用于
@ConfigurationProperties
。@M.Deinum您是对的,请添加您的注释作为答案,我会接受它。PropertySourcePlaceholderConfigurer也不会将加载的道具放入环境中。我想这就是
@ConfigurationProperties
所使用的。
file.name=yourpath
@PropertySource(value="file:${dir.data}/foo.properties", ignoreResourceNotFound=true)
--spring.config.additional-location=file:${dir.data}/foo.properties