Spring Framework 中@PropertySource 和@DynamicPropertySource 的区别

AR1*_*AR1 0 spring spring-boot

属性 @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);
 } }
Run Code Online (Sandbox Code Playgroud)

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

AR1*_*AR1 5

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

注释@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());
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

@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);
    }

}
Run Code Online (Sandbox Code Playgroud)