【问题标题】:Kotlin @ConstructorBinding @ConfigurationProperties class for multiple instancesKotlin @ConstructorBinding @ConfigurationProperties 类用于多个实例
【发布时间】:2020-08-26 18:09:21
【问题描述】:

我遇到了一个问题,我找不到任何好的解决方案。一些背景:我们使用几个微服务,其中大多数使用休息客户端。我们发现他们中的很多人会使用类似的配置来解决类似的问题(即弹性)。自然,我们希望将常见的、大量重复的、非业务代码提取到库中。但问题是:如何在库中提取 @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
)
  • 使用@ConfigurationProperties 将属性实例化为@Bean 方法,但这也不能很好地工作,因为它迫使我将带有@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
    )

}

【问题讨论】:

标签: spring-boot kotlin


【解决方案1】:

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

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

【讨论】:

  • 感谢您的回答!虽然我理解这些陈述背后的逻辑,但我并没有真正看到它们适用于我的问题。我最终拥有了 3 个类(在 2 个服务之间划分)(很快还会有更多),它们具有与 Resilience4j 相关的重复属性(host 地址除外),它们几乎总是具有相同的默认值。对我来说,把它放在一个库中以便更好地维护是很有意义的。说到耦合,这纯粹是 Resilience4j 相关的,可以用于任何需要配置弹性客户端的项目。
  • Resilience4j 这是一个很好的工具,但您确定网格中的每个微服务都具有相同的弹性要求以共享此配置吗?对我来说,你试图实现的目标是过度设计。
  • 我的库将主要包含实用程序,以方便一些类(ClientProperties 和 Client)的配置和经常重复的分解代码。关于属性,是的,我的大部分服务都有默认值,如果其中一个或几个需要更改,我会在 application.properties 中进行。这就是为什么我试图找到一种方法在库中提取这些内容。我的示例显示了 3 个字段,但实际上 3 个类中有 20 个字段。这不是工程过度,这主要是维护问题。
猜你喜欢
  • 1970-01-01
  • 2021-06-03
  • 2018-06-27
  • 2020-07-24
  • 2020-06-09
  • 2021-07-07
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
相关资源
最近更新 更多