繁体   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