1. 概述

在设计Spring Boot应用时,我们通常希望使用外部配置来定义应用程序属性。这样可以在不同的环境中复用代码。有时,我们可能希望在一个环境中使用多个YAML配置文件

在这个教程中,我们将学习两种在创建Spring Boot应用时加载多个YAML配置文件的方法。

2. 使用Spring Profile

将多个YAML配置文件包含在应用中的一个方法是使用Spring Profile

这种方法利用了Spring自动加载与应用Profile相关的YAML配置文件的功能。

接下来,让我们通过一个例子来进行说明,涉及两个.yml文件。

2.1. YAML设置

我们的第一个文件列出了学生。我们将其命名为application-students.yml,并放在./src/main/resources目录下:

students:
  - Jane
  - Michael

第二个文件名为application-teachers.yml,也放在同一个./src/main/resources目录下:

teachers:
  - Margo
  - Javier

2.2. 应用

现在,我们来搭建示例应用。我们将使用应用中的[*CommandLineRunner*](/spring-boot-console-app#console-application)来看配置文件的加载情况:

@SpringBootApplication
public class MultipleYamlApplication implements CommandLineRunner {

    @Autowired
    private MultipleYamlConfiguration config;

    public static void main(String[] args) {
        SpringApplication springApp = new SpringApplication(MultipleYamlApplication.class);
        springApp.setAdditionalProfiles("students", "teachers");
        springApp.run(args);
    }

    public void run(String... args) throws Exception {
        System.out.println("Students: " + config.getStudents());
        System.out.println("Teachers: " + config.getTeachers());

    }
}

在这个例子中,我们通过setAdditionalProfiles()方法程序式地设置额外的Spring Profile

我们也可以在通用的application.yml文件中使用spring.profiles.include参数

spring:
  profiles:
    include:
      - teachers
      - students

这两种方法都可以设置Profile,在应用启动时,Spring会加载符合application-{profile}.yml模式的任何YAML配置文件。

2.3. 配置

为了完成这个例子,让我们创建配置类。它会从YAML文件加载属性:

@Configuration
@ConfigurationProperties
public class MultipleYamlConfiguration {

    List<String> teachers;
    List<String> students;

    // standard setters and getters

}

运行应用后,让我们检查日志:

c.b.p.m.MultipleYamlApplication : The following 2 profiles are active: "teachers", "students"

输出如下:

Students: [Jane, Michael]
Teachers: [Margo, Javier]

尽管这种方法有效,但它的缺点是使用了Spring Profile功能,这可能并不是Spring实现的初衷

考虑到这一点,让我们来看看另一种更稳健的方法,用于加载多个YAML文件。

3. 使用@PropertySources

我们可以通过@PropertySources注解和使用@PropertySource加载YAML来指定多个YAML配置文件。

3.1. 应用

让我们用类似的应用再试一次:

@SpringBootApplication
public class MultipleYamlApplication implements CommandLineRunner {

    @Autowired
    private MultipleYamlConfiguration config;

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

    public void run(String... args) throws Exception {
        System.out.println("Students: " + config.getStudents());
        System.out.println("Teachers: " + config.getTeachers());

    }
}

需要注意的是,此例中我们没有设置Spring Profile

3.2. ConfigurationPropertySourceFactory

现在,让我们实现配置类:

@Configuration
@ConfigurationProperties
@PropertySources({
        @PropertySource(value = "classpath:application-teachers.yml", factory = MultipleYamlPropertySourceFactory.class),
        @PropertySource(value = "classpath:application-students.yml", factory = MultipleYamlPropertySourceFactory.class)})
public class MultipleYamlConfiguration {

    List<String> teachers;
    List<String> students;

    // standard setters and getters

}

@PropertySources注解包括了我们希望在应用中使用的每个YAML文件的@PropertySourcefactory是一个自定义的PropertySourceFactory,它允许加载YAML文件:

public class MultipleYamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
}

运行我们的MultipleYamlApplication,我们可以看到预期的输出:

Students: [Jane, Michael]
Teachers: [Margo, Javier]

4. 总结

在这篇文章中,我们探讨了在Spring Boot应用中加载多个YAML配置文件的两种可能方法。

如往常一样,我们的示例代码的完整源码可以在GitHub上找到