首页 > 解决方案 > Spring框架中@PropertySource和@DynamicPropertySource的区别

问题描述

属性 @DynamicPropertySource 作为 Spring Framework 5.2.5 版的一部分添加。官方文档说:

此注解及其支持基础设施最初旨在允许基于 Testcontainers 的测试的属性轻松地暴露给 Spring 集成测试。但是,此功能也可以与任何形式的外部资源一起使用,其生命周期在测试的 ApplicationContext 之外维护。

还有一个基本的例子:

@SpringJUnitConfig(...)
@Testcontainers 
class ExampleIntegrationTests { 
@Container 
static RedisContainer redis = new RedisContainer(); // ...
@DynamicPropertySource 
static void redisProperties(DynamicPropertyRegistry registry) { 
registry.add("redis.host", redis::getContainerIpAddress);
 registry.add("redis.port", redis::getMappedPort);
 } }

但是,我不明白......当我们拥有行为相同的@PropertySource时,这个新注释的用例是什么?

标签: springspring-boot

解决方案


我最终在导致提交 @DynamicPropertySource 注释的这个 Github问题中找到了答案。

注释@PropertySource:

主要用于使用 Spring Environment 接口从属性文件中读取

可以在这篇不错的文章中找到它的使用示例。

@DynamicPropertySource 用于:

可以更轻松地从作为运行集成测试的一部分引导的其他内容设置配置属性。

 这也有助于使用测试容器设置集成测试,摆脱大量样板代码。

虽然在这种情况下缺少文档,但可以在Spring.io 网站上的此博客中找到一篇非常好的文章。根据上面的文章,示例是:

@SpringBootTest
@Testcontainers
@ContextConfiguration(initializers = ExampleIntegrationTests.Initializer.class)

class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    static class Initializer implements
            ApplicationContextInitializer<ConfigurableApplicationContext> {

        @Override
        public void initialize(ConfigurableApplicationContext context) {
            TestPropertyValues.of("spring.data.neo4j.uri=" + neo4j.getBoltUrl())
                    .applyTo(context.getEnvironment());
        }

    }

}

@DynamicPropertySource 注释可以使上面的测试更清晰,消除样板代码,如下例所示:

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }

}

推荐阅读