[spring-projects/spring-boot]基于 var 的属性的默认值未正确记录

2024-04-20 998 views
2

从Kotlin 编写的@ConfigurationProperties项目生成配置元数据不适用于 defaultValue 字段。它适用于所有其他领域。在java中,它适用于所有事情。这是一个例子。请注意,我使用的是 Spring Boot 2.0 和 Gradle。

kapt 'org.springframework.boot:spring-boot-configuration-processor'
kapt {
  arguments {
    arg("org.springframework.boot.configurationprocessor.additionalMetadataLocations", "$projectDir/src/main/resources")
   }
}
compileJava.dependsOn(processResources)

我的 @ConfigurationProperties 文件如下所示:

@Component
@ConfigurationProperties("flowr.epg")
class EpgProperties {
    /** Whether or not schedules should be computed/refreshed on (re)start */
    var refreshOnRestart = true
    /** Number of threads used to store new images */
    var nImagesUploadThreads = 10
}

结果如下:

{
  "hints": [],
  "groups": [
    {
      "sourceType": "com.taktik.flowr.epg.properties.EpgProperties",
      "name": "flowr.epg",
      "type": "com.taktik.flowr.epg.properties.EpgProperties"
    }
  ],
  "properties": [
{
  "sourceType": "com.taktik.flowr.epg.properties.EpgProperties",
  "defaultValue": false,
  "name": "flowr.epg.refresh-on-restart",
  "description": "Whether or not schedules should be computed\/refreshed on (re)start",
  "type": "java.lang.Boolean"
},
{
  "sourceType": "com.taktik.flowr.epg.properties.EpgProperties",
  "defaultValue": 0,
  "name": "flowr.epg.n-images-upload-threads",
  "description": "Number of threads used to store new images",
  "type": "java.lang.Integer"
}
}

对于我的公司来说,支持 Kotlin 中的默认值将是一个非常好的功能。

注意:复制自https://stackoverflow.com/questions/53636533/spring-boot-configurationproperties-metadata- Generation-wrong-default-values

回答

2

实际上更糟。它不会检测默认值并使用基础类型的默认值。我想我们需要看看是否不能像我们为 Java 编译器所做的那样连接到一些低级 API。

0

我看到同样的问题。需要明确的是:问题仅在于生成的元数据,Kotlin 中指定的默认值@ConfigurationProperties确实会被获取,它们只是没有记录在元数据中,对吧?

4

正确的。

2

不幸的是,目前我们无能为力,请投票给KT-30164。同时,我们可以尝试检测源模型是 Kotlin 类,然后停用默认处理以避免在元数据中写入错误值。

5

好的,是的,我想同时这样做是个好主意。感谢你所做的一切!

7

它适用于所有其他领域。

@Simon3 这与我的分析不符。您能否分享一个示例,其中其他 Kotlin 字段在生成的元数据中具有正确的默认值? (我可以运行的一个小项目是理想的)。谢谢!

0

我的意思是“名称”、“描述”和“类型”字段总是正确的。但“defaultValue”字段总是不正确。我的第一篇文章中的例子对此进行了说明。

4

太棒了,我们现在意见一致了。感谢您的反馈。

7

不幸的是,kotlin 方面还没有取得足够的进展来实现这一点。我的直觉是可能需要另一个钩子点(Kotlin 编译器插件?)。我们将适应我们可用的一切,我将相应地更新此问题。

3

这事有进一步更新吗?KT-30164现已修复。

4

@m-kay 我需要仔细检查,但我认为这对于大多数用例来说并没有太大改变

此外,从 Kotlin 1.4 开始,编译器将仅发出 const val 的值属性。

这绝对对我们想要实现的目标没有帮助。

0

KT-30164 在 1.3.70 中被标记为已修复,而 Kotlin 1.3.70 刚刚发布。我们刚刚将项目更新到该版本,重建后现在包含我们的配置属性的spring-configuration-metadata.json正确内容。defaultValue

所以这对我来说似乎是固定的,或者至少有些东西已经变得更好了。

2

@darioseidl 感谢您的推动。我们将升级1.3.70并重新审视这一点。我有很多测试用例,很高兴听到您的用例按预期工作。

2

@darioseidl 我一直无法defaultValues在 中正确生成spring-configuration-metadata.json,您能仔细检查一下吗?我已经发布了我的重现项目,您能看一下并向我发送您的反馈吗?

4

默认值现在对我来说也很好用!关于我原来的帖子,我所要做的就是将 Kotlin 升级到 1.3.70 :) 谢谢 snicoll!

8

好吧,我发现了区别,它适用于常规var属性,但不适用于@ConstructorBinding.

作品:

@ConfigurationProperties("demo")
class DemoProperties {
    var title: String = "foo"
}

不起作用,需要@DefaultValue正确defaultValues生成元数据:

@ConstructorBinding
@ConfigurationProperties("demo")
class DemoProperties(val title: String = "foo")

此问题已在 Kotlin 端通过https://youtrack.jetbrains.com/issue/KT-29355进行跟踪。

2

啊,是的,我们正在使用var属性并且它对它们有用。我们还没有尝试过@ConstructorBinding

5

此问题已被 Kotlin 中的修复程序取代,请参阅 KT-301642.2.6如果您覆盖 Kotlin1.3.70或更高版本,此功能将可用。

2

根据 @snicoll 的最后评论,这似乎意味着要关闭。

9

谢谢@izeye。

7

与 kotlin 1.5.0 遇到同样的问题

@ConfigurationProperties("gateway.auth")
@Component
class AuthFilterConfig {
  /**
   * filter order
   */
  var order = 200
}
{
      "name": "gateway.auth.order",
      "type": "java.lang.Integer",
      "description": "filter order",
      "sourceType": "fy.eurekagateway.auth.AuthFilterConfig"
    }
3

@rainmanhhh 感谢您告诉我们。这听起来像是 Kotlin 1.5 中的回归。假设它在 Kotlin 1.4 及更早版本中仍能按预期工作,您能否提出有关 JetBrains 引用KT-30164 的问题?

3

仅供参考:尝试了maven插件,没问题(除了枚举字段)。 kapt gradle 插件忽略所有默认值

2

我认为我们以前没有见过这种行为差异。对于早期版本的 Kotlin 来说,它的表现如何?

2

Kotlin 1.7 和 2022.2.2 也存在同样的问题。使用时要么根本不选取默认值(如字符串),要么仅设置为 0(对于 Int)@ConstructorBinding

4

@spyro2000 如上所述,这很可能是 Kotlin 中的回归。您检查过早期版本的行为吗?

9

@wilkinsona:不,我没有。仅使用当前版本 1.7(.10) 进行了测试。

8

IMO,值得检查。如果它适用于早期版本,您可以向 JetBrains 报告回归情况。

3

Kotlin 1.7.20 和 Spring Boot 2.7.6 - 相同的问题,Long 默认为 0

data class MyClass(
  val fixedBackoffAttempts: Long = 10,
)
"defaultValue": 0

在生成的 JSON 中

与注释一起使用@DefaultValue("1")

9

在没有任何相反证据的情况下,Kotlin 的回归是最有可能的原因,我上面的评论仍然有效。

6

如果得到确认,我将在 Kotlin 方面检查并提出问题。

9

如果我没有记错的话,我认为它从未起作用,并且根据设计不可能通过反射检索默认值,因为默认值可能是取决于KT-56893中提到的其他参数的表达式。