1、简介 {#1简介}
本文将带你了解一个相对较新的 Spring Boot 条件注解 @ConditionalOnThreading
。
2、条件注解 {#2条件注解}
条件注解提供了一种仅在满足各种特定条件时才在 BeanFactory
中注册 Bean 的方法。开发人员通过使用 Condition
接口为每个注解单独定义这些条件。
Spring Boot 为常见用例提供了大量预定义的条件注解。常见的示例有 @ConditionalOnProperty
、@ConditionalOnBean
和 @ConditionalOnClass
。
3、@ConditionalOnThreading
原理 {#3conditionalonthreading-原理}
@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、使用示例 {#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 其中的一个:platformBean
或 virtualBean
。
测试代码如下:
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、总结 {#5总结}
本文介绍了 Spring Boot 3.2 中的新条件注解 - @ConditionalOnThreading
。只有当 Spring 通过属性在内部配置为使用指定类型的线程时,该注解才允许创建 Bean。
参考:https://www.baeldung.com/spring-conditionalonthreading