Spring Boot @ConditionalOnThreading 注解

1、简介

本文将带你了解一个相对较新的 Spring Boot 条件注解 @ConditionalOnThreading

2、条件注解

条件注解提供了一种仅在满足各种特定条件时才在 BeanFactory 中注册 Bean 的方法。开发人员通过使用 Condition 接口为每个注解单独定义这些条件。

Spring Boot 为常见用例提供了大量预定义的条件注解。常见的示例有 @ConditionalOnProperty@ConditionalOnBean@ConditionalOnClass

3、@ConditionalOnThreading 原理

@ConditionalOnThreading 只是 Spring Boot 中另一个预定义的条件注解。它是在 3.2 版本中添加的,在本文撰稿时,该版本本身还是候选发布版。也就是说,需要使用专用的 Spring Artifacts 仓库。

<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
        <enabled>false</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/snapshot</url>
        <releases>
        <enabled>false</enabled>
        </releases>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
        <enabled>false</enabled>
        </snapshots>
    </pluginRepository>
    <pluginRepository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/snapshot</url>
        <releases>
        <enabled>false</enabled>
        </releases>
    </pluginRepository>
</pluginRepositories>

@ConditionalOnThreading 注解仅允许在 Spring 内部配置为使用特定类型的线程时创建 Bean。所谓线程类型,是指平台线程或虚拟线程。回顾一下,从 Java 21 开始,我们就可以 使用虚拟线程来代替平台线程 了。

要配置 Spring 在内部使用虚拟线程,使用一个名为 spring.threads.virtual.enabled 的属性。如果该属性为 true,并且正在使用 Java 21 或更高版本,则 @ConditionalOnThreading 注解将允许创建该 Bean。

4、使用示例

假设我们有两个使用 @ConditionalOnThreading 注解的 Bean:

@Configuration
static class CurrentConfig {

    @Bean
    @ConditionalOnThreading(Threading.PLATFORM)
    ThreadingType platformBean() {
        return ThreadingType.PLATFORM;
    }

    @Bean
    @ConditionalOnThreading(Threading.VIRTUAL)
    ThreadingType virtualBean() {
        return ThreadingType.VIRTUAL;
    }
}

enum ThreadingType {
    PLATFORM, VIRTUAL
}

通过 ConditionalOnThreading 注解,我们将创建这两个 Bean 其中的一个:platformBeanvirtualBean

测试代码如下:

ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
  .withUserConfiguration(CurrentConfig.class);

@Test
@EnabledForJreRange(max = JRE.JAVA_20)
public void whenJava20AndVirtualThreadsDisabled_thenThreadingIsPlatform() {
    applicationContextRunner.withPropertyValues("spring.threads.virtual.enabled=false").run(context -> {
        Assertions.assertThat(context.getBean(ThreadingType.class)).isEqualTo(ThreadingType.PLATFORM);
    });
}

@Test
@EnabledForJreRange(min = JRE.JAVA_21)
public void whenJava21AndVirtualThreadsEnabled_thenThreadingIsVirtual() {
    applicationContextRunner.withPropertyValues("spring.threads.virtual.enabled=true").run(context -> {
        Assertions.assertThat(context.getBean(ThreadingType.class)).isEqualTo(ThreadingType.VIRTUAL);
    });
}

@Test
@EnabledForJreRange(min = JRE.JAVA_21)
public void whenJava21AndVirtualThreadsDisabled_thenThreadingIsPlatform() {
    applicationContextRunner.withPropertyValues("spring.threads.virtual.enabled=false").run(context -> {
        Assertions.assertThat(context.getBean(ThreadingType.class)).isEqualTo(ThreadingType.PLATFORM);
    });
}

如上,使用了 ApplicationContextRunner 实例,它为测试创建了一个轻量级应 Application Context。用它来设置 Spring 属性 spring.threads.virtual.enabled 的值。还为测试添加了 @EnabledForJreRange 注解。该注解允许仅在特定的 Java 版本上运行测试。

5、总结

本文介绍了 Spring Boot 3.2 中的新条件注解 - @ConditionalOnThreading。只有当 Spring 通过属性在内部配置为使用指定类型的线程时,该注解才允许创建 Bean。


参考:https://www.baeldung.com/spring-conditionalonthreading