首页 > 解决方案 > Kotlin @ConstructorBinding @ConfigurationProperties 类用于多个实例

问题描述

我遇到了一个问题,我找不到任何好的解决方案。一些背景:我们使用几个微服务,其中大多数使用休息客户端。我们发现他们中的很多人会使用类似的配置来解决类似的问题(即弹性)。自然,我们希望将常见的、大量重复的、非业务代码提取到库中。但事情是这样的:如何@ConstructorBinding @ConfigurationProperties在库中提取数据类(特别是如果在使用该库的代码库中可能有这些类的多个实例)?

这是一些示例代码:

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

我想将其导入项目以配置 2 个不同的 REST 客户端。我试过了:

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
)
@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
    )

}

标签: spring-bootkotlin

解决方案


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

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

推荐阅读