如何在 Spring Boot 中通过 @ConfigurationProperties 获取嵌套的基于 Spel 表达式的对象?

How to get nested Spel expression based objects through @ConfigurationProperties in Spring Boot?

这是我的 application.yml

translations:
  en:
    title: 'english'
    description: 'english text'
  fr:
    title: 'french'
    description: 'french text'
  de:
    title: 'german'
    description: 'french text'

codes:
  GB:
    # I am assuming that en here will have an object with both title and description properties
    en: ${translations.en}
  CA:
    en: ${translations.en}
    fr: ${translations.fr}
  DE:
    en: ${translations.en}
    fr: ${translations.fr}
    de: ${translations.de}

现在考虑这段代码(删除了不必要的 getter 等,为了简洁起见还使用 project lombok

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
    // Inner classes, but these can be outside as well
    @ConfigurationProperties
    @Getter
    @Component
    class Config {
        Map<String, Map<String, LanguageDTO>> codes;
    }

    @Data
    @AllArgsConstructor
    class LanguageDTO {
        String title;
        String description;
    }

    @Autowired
    Config config;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        // Getting error on this line below
        Map<String, Map<String, LanguageDTO>> codes = config.getCodes();
    }
}

现在,当我启动应用程序时,出现如下错误:

APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'codes.gb.en' to com.example.demo.DemoApplication$LanguageDTO:

    Property: codes.gb.en
    Value: ${translations.en}
    Origin: class path resource [application.yml]:24:9
    Reason: No converter found capable of converting from type [java.lang.String] to type [com.example.demo.DemoApplication$LanguageDTO]

Action:

Update your application's configuration

我想要什么?

我希望能够像 Map<String, Map<String, LanguageDTO> 一样阅读代码。也就是说,我应该能够做到 config.getCodes().get("GB").get("en") --> 其数据类型应为 LanguageDTO.

我认为它不可行:Spring 仅支持 application.yaml 文件中的简单 属性 占位符(据我所知)。不过,您可以做的是利用 YAML 格式 built-in 功能,anchors and aliases:

translations:
  en: &en
    title: 'english'
    description: 'english text'
  fr: &fr
    title: 'french'
    description: 'french text'
  de: &de
    title: 'german'
    description: 'french text'

codes:
  GB:
    en: *en
  CA:
    en: *en
    fr: *fr
  DE:
    en: *en
    fr: *fr
    de: *de

For it to work, the LanguageDTO class needs to have setters and a default constructor. @AllArgsConstructor won't work. Alternatively you might try to get it work in conjunction with constructor binding, although I'm not sure if it's possible.