繁体   English   中英

记录中嵌套的 Spring 配置(ConfigurationProperties)

[英]Nested Spring configuration (ConfigurationProperties) in records

一个 map application.yaml如何具有嵌套属性的 yaml 配置与 Java 中的类似记录结构?

例如,如果我们有以下 yaml:

foo:
    bar:
        something: 42

    baz:
        otherThing: true

    color: blue

所需的记录结构将类似于以下内容:

@ConfigurationProperties(prefix = "foo")
@ConstructorBinding
public record Foo(
    Bar bar,
    Baz baz,
    String color
) {}

// ---

@ConfigurationProperties(prefix = "foo.bar")
@ConstructorBinding
public record Bar(
    int something
) {}

// ---

@ConfigurationProperties(prefix = "foo.baz")
@ConstructorBinding
public record Baz(
    boolean otherThing
) {}

对于每个嵌套的 class,您不需要@ConfigurationProperties 它仅适用于根 class (Foo.class)。 然后通过在 class 上方插入@Component或将@ConfigurationPropertiesScan放在应用程序 class 上,将 Foo 设置为 Spring Bean。

原来我没有针对我遇到的问题提出正确的问题:/ 因此,对于人们从类似问题中找到这个主题的情况,我的实际问题的答案如下。

嵌套 yaml 试图在 model 层次结构上“捷径”出现问题,因此给出以下 yaml:

foo:
    bar:
        baz:
            bum: "hello"

我试图 model 的层次结构如下:

@ConfigurationProperties(prefix = "foo")
@ConstructorBinding
public record Foo(BarBaz barBaz) {}

// --- 

@ConfigurationProperties(prefix = "foo.bar.baz")
@ConstructorBinding
public record BarBaz(String bum) {}

这里出现的问题是Foo不能为BarBaz进行构造函数绑定(不知道为什么)。 因此,我发现了两种可能的解决方案:

1.做全建模(决定这是我比较喜欢的)

也就是说,不要试图跳过bar的中间 model 。

@ConfigurationProperties(prefix = "foo")
@ConstructorBinding
public record Foo(Bar bar) {}

// ---

@ConfigurationProperties(prefix = "foo.bar")
@ConstructorBinding
public record Bar(Baz baz) {}

// --- 

@ConfigurationProperties(prefix = "foo.bar.baz")
@ConstructorBinding
public record Baz(String bum) {}

2.嵌入更多嵌套时不要使用@ConstructorBinding

只需跳过Foo中的构造函数绑定。

@ConfigurationProperties(prefix = "foo")
public record Foo(BarBaz barBaz) {}

// --- 

@ConfigurationProperties(prefix = "foo.bar.baz")
@ConstructorBinding
public record BarBaz(String bum) {}

虽然更简单,但它不太一致。

我认为为简化起见,您可以只创建一个文件:

@ConfigurationProperties(prefix = "foo")
public record Foo(Bar bar) {
    public record Bar(Baz baz) {
        public record Baz(String bum) {}    
    }
}

这在 spring-boot 中运行良好,您无需重复注释,使用时只需使用:

String bumVal = foo.bar().baz().bum();

其中 foo 只是注入到您需要它的 Bean(s) 中。

我什至删除了@ConsructorBinding ,因为从 spring-boot 2.6 开始,只要记录只定义一个构造函数,就不再需要它了,请参阅发行说明

上面的配置与你自己的答案结构有关,但这里也是原始问题结构的紧凑方式:

@ConfigurationProperties(prefix = "foo")
public record Foo(Bar bar, Baz baz, String color) {
    public record Bar(String something) {
    }
    public record Baz(String otherThing) {
    }   
}

我发现record类型对于这个用例非常有用,因为它非常紧凑并且不需要编写太多代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM