当前位置: 首页 > 知识库问答 >
问题:

迁移到带有命名冲突的@ConfigurationProperties

南门新知
2023-03-14

我有一个带有应用程序的Spring Boot应用程序。属性如下所示的文件:

setting.mode = a # Can be either `a` or `b`
setting.mode.a.subsetting1 = abc
setting.mode.a.subsetting2 = def
setting.mode.b.subsetting1 = ghi
setting.mode.b.subsetting2 = jkl

我们过去常常使用@Value注释来读取这些值,因此字符串设置的名称并不重要。模式与“子设置”的前缀相同。

我的任务是清理这个应用程序,我想使用与属性文件内容相匹配的大型配置对象来使用@ConfigurationProperties,以使代码更易于使用。

我认为configuration类的结构应该是这样的(Kotlin示例,但这并不重要):

@Component
@ConfigurationProperties("setting")
class MyProperties {

    // Has the value either `a` or `b` to tell us which component to use
    lateinit var mode: String

    // THE PROBLEM IS HERE
    // -------------------
    //
    // The two classes below need to be under the `mode`
    // prefix, but they can't be because it is already used
    // to get its String value above.

    val a = A()

    val b = B()

    class A {
        lateinit var subsetting1: String
        lateinit var subsetting2: String
    }

    class B {
        lateinit var subsetting1: String
        lateinit var subsetting2: String
    }
}

请注意,设置的值。模式也用于决定注册哪个bean

@Bean
@ConditionalOnProperty(name = ["setting.mode"], havingValue = "a")
fun a(properties: MyProperties): CommonInterface {
    return A(properties.mode.a)
}

@Bean
@ConditionalOnProperty(name = ["setting.mode"], havingValue = "b")
fun b(properties: MyProperties): CommonInterface {
    return B(properties.mode.b)
}

如何设置此配置(无需重写application.properties以消除此应用程序所有实例的命名问题)?

共有1个答案

柳英豪
2023-03-14

正确的方法是不要使用一个包含所有嵌套类的ConfigurationProperties类来构建整个结构,因为这意味着您不必要地填充了您知道不会使用的部分,因为它们对应的bean没有注册。

执行此操作的最佳方法是将配置类AB如下所示:

@Component
@ConfigurationProperties("setting.mode.a")
class AProperties {
    lateinit var subsetting1: String
    lateinit var subsetting2: String
}

@Component
@ConfigurationProperties("setting.mode.b")
class BProperties {
    lateinit var subsetting1: String
    lateinit var subsetting2: String
}

然后更改@Bean定义以直接使用这些类,而不是调用整个配置对象:

@Bean
@ConditionalOnProperty(name = ["setting.mode"], havingValue = "a")
fun a(properties: AProperties): CommonInterface {
    return A(properties)
}

@Bean
@ConditionalOnProperty(name = ["setting.mode"], havingValue = "b")
fun b(properties: BProperties): CommonInterface {
    return B(properties)
}
 类似资料:
  • 目前,我们公司通过手动创建、分发和运行必要的SQL脚本来处理所有数据库模式更改。显然,这会导致各种机器偶尔更新和稀疏更新的问题。 我正在研究更现代的方法来解决这个问题,而Flyway现在是主要的候选人(尽管如果可以提出令人信服的论据,我们仍然愿意使用Liquibase)。 正常流程很简单,和宣传的一样简单,但是我们不知道如何正确处理冲突的迁移脚本。例如,不同个人分支(A和B)上的2名开发人员在不同

  • 在实现第三方API(mollie)时,他们似乎将支持分页的参数之一命名为from,这与内置的python相冲突。 有没有办法让我正确使用这个?我没有正确传递参数吗?注意:它们被写成。 它唯一支持的参数是:和。 给予:

  • 我正在进行迁移,这个特殊的库在中显示错误,而在中没有错误

  • 问题内容: 我犯了如下错误: 但是现在我想使用内置函数。如您所见,listname和内置函数之间存在命名冲突。 如何在不重新启动Python Shell的情况下将变量作为内置函数使用? 问题答案: 使用或(取决于上下文),或再次简单地删除()。 无需进口: 存在是CPython实现细节;在模块中,它是一个模块,在其他任何地方,它都是模块字典。Jython,IronPython和PyPy可能选择完全

  • .在我的日志中,当我试图升级apk时,我得到以下信息: .orginal应用程序已经生产了4年多,是用Eclipse编写的,它安装在我的旧硬盘上。 六个月前,我的老板给我买了一个SSD驱动器,我安装了Android Studio。我迁移了旧的项目,它构建良好,它将安装到一个设备上,没有安装以前的版本。 谁能告诉我为什么Android说我的升级是用不同的密钥签名的? [更新1] 我已经提取了新旧AP

  • 问题内容: 如您所知,角形和细枝形都有共同的控制结构-双花括号。如何更改Angular的默认值? 我知道我可以在Twig中做到这一点,但是在某些项目中,我只能做到JS。 问题答案: 您可以使用service 更改开始和结束插值标签。一个方便的地方是在模块初始化时。 https://docs.angularjs.org/api/ng/provider/$interpolateProvider