Kotlin @ConstructorBinding @ConfigurationProperties类用于多个实例

时间:2020-05-11 08:47:31

标签: spring-boot kotlin

我遇到了一个问题,我找不到很好的解决方案。一些背景:我们使用几种微服务,其中大多数使用其他客户端。我们发现,其中许多将针对相似的问题(即弹性)使用相似的配置。自然地,我们希望将常见的,大量重复的非业务代码提取到库中。但这就是问题:我如何在一个库中提取一个@ConstructorBinding @ConfigurationProperties数据类(尤其是在使用该库的代码库中这些类的多个实例)?

这是一些示例代码:

@ConstructorBinding
@ConfigurationProperties(prefix = "rest.client")
data class MyDuplicatedRestClientProperties(
    val host: String,
    val someOtherField: Int,
    val someFieldWithDefaultValue: String = "default value"
)

我想将此导入到项目中以配置2个不同的REST客户端。我尝试过:

  • 创建一个抽象类,我的ClientProperties将会扩展。可悲的是,我需要公开父类的所有字段,而这些字段实际上对复制没有帮助:
abstract class MyAbstractClient(
    val host: String,
    val someOtherField: Int,
    val someFieldWithDefaultValue: String = "default value"
)
@ConstructorBinding
@ConfigurationProperties(prefix = "rest.client")
class MyImplematationClient(
    val host: String,
    val someOtherField: Int,
    val someFieldWithDefaultValue: String = "default value"
): MyAbstractClient(
    host,
    someOtherField,
    someFieldWithDefaultValue
)
  • 使用@Bean将属性实例化为@ConfigurationProperties方法,但这也不起作用,因为它迫使我将@Value的字段放入@Configuration类中:
@Configuration
class MyConfigurationClass {

    @Value("${my.client.host}")
    lateinit var host: String

    @Value("${my.client.someOtherField}")
    lateinit var someOtherField: Int

    @Value("${my.client.someFieldWithDefaultValue:default value}")
    lateinit var someFieldWithDefaultValue: String

    @Bean
    @ConfigurationProperties
    fun myClient() = MyDuplicatedRestClientProperties(
        host,
        someOtherField,
        someFieldWithDefaultValue
    )

}

1 个答案:

答案 0 :(得分:1)

根据我的经验,您走错了路。为什么?

  1. 允许在微服务中进行复制。代码不是太大,它已解耦并且可以轻松更改。
  2. 根据分布式系统理论,在多个组件之间共享类是一件坏事。为什么?因为这样做会通过这些类耦合组件。
  3. 更好的方法是将所有集成封装到特定的库中,例如REST客户端。例如,访问服务A可以通过service-a-client.jar完成,该服务将包含调用服务A所必需的配置和集成,并将公开一个或多个可用作{{ 1}}。
  4. 将配置放入库不会给您带来任何优势,配置与业务无关,它们某种程度上是合成对象,在体系结构中没有价值。