首页 > 解决方案 > Spring Boot 使用 ConfigurationProperties 从 .properties 和 .yaml 注入 Map 值

问题描述

当我尝试Map.properties文件和.yaml文件注入 a 时,我注意到 Spring 中的行为有所不同。我正在使用 SpringConfigurationProperties来执行此操作。

文件:

products.yaml

test-service:
  products:
    1: alpha
    2: bravo
    3: charlie

products.properties

test-service.products.1=alpha
test-service.products.2=bravo
test-service.products.3=charlie

ProductProperties加载属性的类:

@ConfigurationProperties("test-service")
public class ProductProperties {

    private final Map<String, String> products = new HashMap<>();

    public Map<String, String> getProducts() {
        return products;
    }
}

单元测试ProductPropertiesPropertiesTest,通过:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ProductProperties.class)
@TestPropertySource("classpath:products.properties")
@EnableConfigurationProperties(ProductProperties.class)
public class ProductPropertiesPropertiesTest {

    @Autowired
    private ProductProperties productProperties;

    @Test
    public void testProperties() {
        assertEquals(3, productProperties.getProducts().size()); // passes
    }
}

单元测试ProductPropertiesYamlTest,失败:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ProductProperties.class)
@TestPropertySource("classpath:products.yaml")
@EnableConfigurationProperties(ProductProperties.class)
public class ProductPropertiesYamlTest {

    @Autowired
    private ProductProperties productProperties;

    @Test
    public void testProperties() {
        assertEquals(3, productProperties.getProducts().size()); // fails
    }
}

两个测试之间的唯一区别是属性的来源:一个.properties文件(通过)和一个.yaml失败的文件。

为什么?

标签: javaspringspring-boot

解决方案


你的代码有两个问题

YAML无法使用PropertySourceTestPropertySource注释加载TestPropertySource文件

@TestPropertySource 是一个类级别的注释,用于配置属性文件的位置()和内联属性(),以添加到环境的一组属性源中,用于集成测试的 ApplicationContext。

YAML 缺点

无法使用 @PropertySource 注解加载 YAML 文件。因此,如果您需要以这种方式加载值,则需要使用属性文件。

因此,将您的yml文件名更改为application.yml,然后您仍然需要@SpringBootTest在测试类上添加注释以从 yml 文件中绑定这些属性

加载 YAML Spring boot 有 binder utils

要通过使用 Spring Boot 的 Binder 实用程序(这是 @ConfigurationProperties 所做的)绑定到类似的属性,您需要在目标 bean 类型为 java.util.List(或 Set)中具有一个属性,并且您需要提供一个 setter或使用可变值对其进行初始化。

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ProductProperties.class)
//default to application.yml
@EnableConfigurationProperties(ProductProperties.class)
@SpringBootTest
public class ProductPropertiesPropertiesTest {

   @Autowired
   private ProductProperties productProperties;

   @Test
   public void testProperties() {
       assertEquals(3, productProperties.getProducts().size()); // passes
     }
 }

但是对于属性文件@SpringBootTest是可选的,因为默认情况下 SpringApplication 从 application.properties 文件加载属性并将它们添加到 Spring Environment


推荐阅读