具有不可变属性的@ConstructorBinding在Spring Boot Kotlin @ConfigurationProperties中不适用于@Value

问题描述:

Spring Boot支持针对 @ConfigurationProperties 的Kotlin data 类.

Spring Boot supports Kotlin data classes for @ConfigurationProperties.

@ConstructorBinding
@ConfigurationProperties(prefix = "prefix")
data class AppProperties (
    val something: String
)

但是 val @ConstructorBinding 有一些限制.您不能将一个变量别名给另一个变量.假设您正在Kubernetes中运行,并且想要捕获由env var HOSTNAME 给出的主机名.最简单的方法是将 @Value("\ $ {HOSTNAME} :)" 应用于属性,但它仅适用于可变属性,而没有构造函数绑定.

But val and @ConstructorBinding has some limitations. You cannot alias one variable to another. Let's say you're running in Kubernetes and want to capture the hostname, which is given by the env var HOSTNAME. The easiest way to do this is to apply @Value("\${HOSTNAME}:)" to a property, but it only works for a mutable property and without constructor binding.

Spring Boot GitHub问题跟踪器说:

The Spring Boot GitHub issue tracker says:

停止!!请询问有关如何使用某物或了解为什么某物不使用的问题使用spring-boot标签在Stack Overflow上按预期工作.

STOP!! Please ask questions about how to use something, or to understand why something isn't working as you expect it to, on Stack Overflow using the spring-boot tag.

那么,这是一个已知的限制吗?还是我应该为他们创建一张票以解决它?

So, is this a known limitation or should I create a ticket for them to fix it?

打开 https://github.com/spring-projects/spring-boot/issues/25552

@ConfigurationProperties

@ConfigurationProperties is an alternative to @Value and the two are not designed to be used together. It may work with JavaBean-style binding but that would be by accident rather than by design and it shouldn't be relied upon.

建议您不要使用 @Value 为通过 @ConfigurationProperties 绑定的内容添加别名,而是建议您通过其他方式进行.例如,您可以使用Marcos Barbero在对您的问题的评论中链接的此答案中建议的一种方法.另外,您也可以从文档中的此示例,并在 application.properties 中使用占位符:

Instead of using @Value to alias something bound via @ConfigurationProperties, it's recommended that you do so via some other means. For example you could use one of the approaches suggested in this answer that Marcos Barbero linked to in the comments on your question. Alternatively, you could take some inspiration from this example in the documentation and use a placeholder in application.properties:

prefix.something=${hostname}

另一种选择是通过 META-INF/spring.factories 注册 EnvironmentPostProcessor 的实现,该实现将 PropertySource 添加到环境中设置所需的别名.目前,如果要在可重用的库中执行某些操作,这可能是最好的方法.一个未解决的问题删除了当前涉及的一些仪式.

Another option would be to register via META-INF/spring.factories an implementation of EnvironmentPostProcessor that adds a PropertySource to the environment to set up the desired aliasing. For the time being, this is probably the best approach if you want to do something in a reusable library. There's an open issue to remove some of the ceremony that's currently involved.