簡體   English   中英

Spring 引導注釋@ConfigurationProperties 不能正常工作與 Kotlin 中的嵌套集合類

[英]Spring boot annotation @ConfigurationProperties doesn't work correctly classes with nested collection in Kotlin

有帶有@ConfigurationProperties 和@ConstructorBinding 的數據class。 此 class 包含集合字段。 有幾個屬性源(application.yml、application-dev1.yml)初始化集合的第一個元素。 此元素的綁定無法正常工作。 初始化值僅從一個屬性源中提取。 預期行為與某些嵌套 class 類型的字段相同:合並來自所有屬性源的值。

Kotlin 屬性 class

@ConfigurationProperties("tpp.test.root")
@ConstructorBinding
data class RootPropperties(
   var rootField1: String = "",
   var rootField2: String = "",
   var nested: NestedProperties = NestedProperties(),
   var nestedList: List<NestedListProperties> = listOf()
) {

data class NestedProperties(
    var nestedField1: String = "",
    var nestedField2: String = ""
)

@ConstructorBinding
data class NestedListProperties(
    var nestedListField1: String = "",
    var nestedListField2: String = ""
)
}

應用程序.yml

tpp:
  test:
    root:
      root-field1: default
      nested:
        nested-field1: default
      nested-list:
        - nested-list-field1: default

應用程序-dev1.yml

tpp:
  test:
    root:
     root-field2: dev1
     nested:
       nested-field2: dev1
     nested-list:
       - nested-list-field2: dev1

測試

@ActiveProfiles("dev1")
@SpringBootTest
internal class ConfigurationPropertiesTest {

@Autowired
lateinit var environment: Environment

@Autowired
lateinit var rootPropperties: RootPropperties

    @Test
    fun `configuration properties binding`() {
         Assertions.assertEquals("default", rootPropperties.rootField1)
         Assertions.assertEquals("dev1", rootPropperties.rootField2)

         Assertions.assertEquals("default", rootPropperties.nested.nestedField1)
         Assertions.assertEquals("dev1", rootPropperties.nested.nestedField2)

         Assertions.assertTrue(rootPropperties.nestedList.isNotEmpty())
         //org.opentest4j.AssertionFailedError:
         //Expected :default
         //Actual   :
         Assertions.assertEquals("default", rootPropperties.nestedList[0].nestedListField1)
         Assertions.assertEquals("dev1", rootPropperties.nestedList[0].nestedListField2)
    }

     @Test
     fun `environment binding`() {
        Assertions.assertEquals("default", environment.getProperty("tpp.test.root.root-field1"))
        Assertions.assertEquals("dev1", environment.getProperty("tpp.test.root.root-field2"))

        Assertions.assertEquals("default", environment.getProperty("tpp.test.root.nested.nested-field1"))
        Assertions.assertEquals("dev1", environment.getProperty("tpp.test.root.nested.nested-field2"))

        Assertions.assertEquals("default", environment.getProperty("tpp.test.root.nested-list[0].nested-list-field1"))
        Assertions.assertEquals("dev1", environment.getProperty("tpp.test.root.nested-list[0].nested-list-field2"))
    }
}

使用 RootProperties 的測試在assertEquals("default", rootPropperties.nestedList[0].nestedListField1)上失敗,因為rootPropperties.nestedList[0].nestedListField1的值為空。 所有其他斷言測試都成功通過。 綁定僅用於收集無法正常工作。

同時環境測試成功通過。 並且Environment.getProperty("tpp.test.root.nested-list[0].nested-list-field1")解析更正值: "default"

Spring 啟動版本:2.6.4

參考文檔的本節介紹

可能的解決方法是將 List 切換到 Map。

屬性 class

@ConfigurationProperties("tpp.test.root-map")
@ConstructorBinding
data class RootMapPropperties(
    var rootField1: String = "",
    var rootField2: String = "",
    var nested: NestedProperties = NestedProperties(),
    var nestedMap: Map<String, NestedMapProperties> = mapOf()
) {

    data class NestedProperties(
        var nestedField1: String = "",
        var nestedField2: String = ""
    )

    data class NestedMapProperties(
        var nestedMapField1: String = "",
        var nestedMapField2: String = ""
    )
}

應用程序.yml

tpp:
  test:    
    root-map:
      root-field1: default
      nested:
        nested-field1: default
      nested-map:
        1:
          nested-map-field1: default

應用程序-dev1.yml

tpp:    
    root-map:
      root-field2: dev1
      nested:
        nested-field2: dev1
      nested-map:
        1:
          nested-map-field2: dev1

測試

@ActiveProfiles("dev1")
@SpringBootTest
internal class ConfigurationPropertiesMapTest {

    @Autowired
    lateinit var environment: Environment

    @Autowired
    lateinit var rootPropperties: RootMapPropperties

    @Test
    fun `configuration properties binding`() {
        Assertions.assertEquals("default", rootPropperties.rootField1)
        Assertions.assertEquals("dev1", rootPropperties.rootField2)

        Assertions.assertEquals("default", rootPropperties.nested.nestedField1)
        Assertions.assertEquals("dev1", rootPropperties.nested.nestedField2)

        Assertions.assertTrue(rootPropperties.nestedMap.isNotEmpty())
        Assertions.assertEquals("default", rootPropperties.nestedMap["1"]!!.nestedMapField1)
        Assertions.assertEquals("dev1", rootPropperties.nestedMap["1"]!!.nestedMapField2)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM