ConfigurationProperties从YML加载列表

时间:2017-08-25 11:35:39

标签: spring kotlin yaml

我试图从YML加载配置。我可以加载值,如果这些是逗号分隔值,我也可以加载列表。但我无法加载典型的YML列表。

配置类

@Component
@PropertySource("classpath:routing.yml")
@ConfigurationProperties
class RoutingProperties(){
    var angular = listOf("nothing")
    var value: String = ""
}

使用routing.yml

angular: /init, /home
value: Hello World

不工作routing.yml

angular:
    - init
    - home

value: Hello World

为什么我无法加载第二个版本的yml /我是否有语法错误?

ENV:Kotlin,Spring 2.0.0.M3

3 个答案:

答案 0 :(得分:3)

正如@flyx所说,@PropetySource无法使用yaml文件。但是在春天你几乎可以覆盖所有东西:)

PropertySource还有其他参数:factory。可以在DefaultPropertySourceFactory

上创建自己的PropertySourceFactory
open class YamlPropertyLoaderFactory : DefaultPropertySourceFactory() {
    override fun createPropertySource(name: String?, resource: EncodedResource?): org.springframework.core.env.PropertySource<*> {
        if (resource == null)
            return super.createPropertySource(name, resource)

        return YamlPropertySourceLoader().load(resource.resource.filename, resource.resource, null)
    }
}

当在factoryysource注释中使用这个工厂时:

@PropertySource("classpath:/routing.yml", factory = YamlPropertyLoaderFactory::class)

最后你需要用mutableList初始化变量angular

完整代码示例:

@Component
@PropertySource("classpath:/routing.yml", factory = YamlPropertyLoaderFactory::class)
@ConfigurationProperties
open class RoutingProperties {
    var angular = mutableListOf("nothing")
    var value: String = ""


    override fun toString(): String {
        return "RoutingProperties(angular=$angular, value='$value')"
    }
}

open class YamlPropertyLoaderFactory : DefaultPropertySourceFactory() {
    override fun createPropertySource(name: String?, resource: EncodedResource?): org.springframework.core.env.PropertySource<*> {
        if (resource == null)
            return super.createPropertySource(name, resource)

        return YamlPropertySourceLoader().load(resource.resource.filename, resource.resource, null)
    }
}

@SpringBootApplication
@EnableAutoConfiguration(exclude = arrayOf(DataSourceAutoConfiguration::class))
open class Application {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val context = SpringApplication.run(Application::class.java, *args)

            val bean = context.getBean(RoutingProperties::class.java)

            println(bean)
        }
    }
} 

答案 1 :(得分:1)

Kinda的旧帖子,我知道。但是我现在处于同一主题。

到目前为止,似乎PropertySource确实适用于yaml文件。给定限制,它仅允许原始类型(看起来),并且它不能处理嵌套元素。我可能会做得更深一些,并相应地更新我的答案,但是到目前为止,可接受的答案似乎是一个可行的解决方法。

答案 2 :(得分:0)

好吧,根据the docs,您的YAML文件将被重写为属性文件。第一个YAML文件变为:

angular=/init, /home
value=Hello World

第二个成为:

angular[0]=init
angular[1]=home
value=Hello World

这显然是两个截然不同的事情,因此表现不同。

此外,稍后在文档中,声明YAML甚至不能与@PropertySource一起使用:

  

24.6.4 YAML缺点

     

无法通过@PropertySource注释加载YAML文件。因此,如果您需要以这种方式加载值,则需要使用属性文件。

这让我很奇怪为什么第一种情况对你有用。

文档说明了生成的…[index]属性:

  

要使用Spring DataBinder实用程序(这是@ConfigurationProperties所做的)绑定到类似的属性,您需要在类型为java.util.List的目标bean中具有属性(或{{ 1}})你需要提供一个setter,或者用一个可变值初始化它,例如这将绑定到上面的属性

所以,让我们来看看Kotlin文档:listOf 返回给定元素的新的只读列表。所以列表不是文档所要求的可变的,我认为这是为什么它不起作用。尝试使用一个可变列表(因为我从未使用过Kotlin,我不能给你工作代码)。如果可能在Kotlin中,也尝试将其声明为Set