Spring 没有 setter 找到 属性

Spring no setter found for property

我正在尝试使用 Spring Boot 在 Kotlin 中进行配置 data class。我有以下 class:

@Configuration
@ConfigurationProperties(prefix = "spring.braintree")
data class BraintreeConfigProperties(
    val merchantId: String = "",
    val publicKey: String = "",
    val privateKey: String = "",
    val environment: Environment = Environment.SANDBOX
)

以及以下属性:

spring.braintree.merchantId=${BRAINTREE_MERCHANT_ID}
spring.braintree.publicKey=${BRAINTREE_PUBLIC_KEY}
spring.braintree.privateKey=${BRAINTREE_PRIVATE_KEY}

当我 运行 应用程序时,出现以下异常:

APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'spring.braintree' to com.x.ps.config.BraintreeConfigProperties$$EnhancerBySpringCGLIB$1e0531:

    Property: spring.braintree.merchant-id
    Value: ${BRAINTREE_MERCHANT_ID}
    Origin: class path resource [application.properties] - 5:29
    Reason: java.lang.IllegalStateException: No setter found for property: merchant-id

Action:

Update your application's configuration

不过,我还有一个class,它和BraintreeConfigProperties class完全一样。这个 class (DatabaseConfigProperties) 确实有效。它们完全相同。

我尝试过的:

  1. 检查 属性 名称是否与配置名称实际匹配。
  2. 分别尝试了所有三个配置属性。
  3. 将值为 1234 的非环境变量附加到 merchantId 属性,这导致以下异常:
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'spring.braintree' to com.x.ps.config.BraintreeConfigProperties$$EnhancerBySpringCGLIB$509e61:

    Property: spring.braintree.merchant-id
    Value: 1234
    Origin: class path resource [application.properties] - 5:29
    Reason: java.lang.IllegalStateException: No setter found for property: merchant-id

Action:

Update your application's configuration

这里的问题是val是最终的,var可以改变。所以你应该将你的属性更改为 var.

更多信息在这里:https://medium.com/mindorks/kotlin-series-val-vs-var-difference-android-kotlin-ecad780daeb7

Kotlin 仅在将字段声明为 val 时生成 getter。 Spring 但是使用 setter 将属性中的值注入到对象中。

使用较新版本的 Spring Boot,您可以使用 data classes 和 val 字段,通过构造函数而不是使用 setters 注入值。

您可以使用 @ConstructorBinding 执行此操作,请参阅 official docs 中的以下示例:

@ConstructorBinding
@ConfigurationProperties("example.kotlin")
data class KotlinExampleProperties(
        val name: String,
        val description: String,
        val myService: MyService) {

    data class MyService(
            val apiToken: String,
            val uri: URI
    )
}

虽然使用 lateinit var 或初始化为 null 的 var 也可以。很可能您不想在初始化后更改这些字段,因此 val 似乎在大多数情况下更适合而不是声明 var 并在后台生成 setter。