1. 引言

在这个快速教程中,我们将探讨Spring Boot新引入的一个相对新颖的注解@ConditionalOnThreading

我们将了解这个注解的条件是什么,以及如何满足这些条件来创建bean。

2. 条件注解

虽然我们已经讨论过Spring Boot中的条件注解,但还是值得简要回顾一下。

条件注解提供了一种方法,只有在满足特定条件时才将bean注册到BeanFactory中。开发者为每个注解单独定义这些条件,通过使用Condition接口。

Spring Boot内置了一些常见的条件注解,例如@ConditionalOnProperty@ConditionalOnBean@ConditionalOnClass

3. @ConditionalOnThreading理论

@ConditionalOnThreading是Spring Boot中的另一个预定义条件注解。它在3.2版本中添加,而本文写作时,3.2版本还是候选发布。要获取这个候选发布的早期访问权限,应使用专用的Spring Maven仓库

@ConditionalOnThreading注解允许创建bean,前提是Spring配置为使用特定类型的线程(平台线程或虚拟线程)。这里的线程类型指的是平台线程或虚拟线程。回想一下,从Java 21开始,我们有能力使用虚拟线程代替平台线程

因此,如果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实例,用于为测试创建轻量级的应用上下文。我们使用它来设置spring属性spring.threads.virtual.enabled的值。我们还为测试注解了@EnabledForJreRange,这允许我们在特定的Java版本上运行测试。

我们可以注意到,对于ThreadingType bean要成为Virtual,必须将属性设置为true且至少是Java 21。否则,注解的条件为false

5. 总结

在这篇短文中,我们探讨了一个新的Spring注解——@ConditionalOnThreading。它是Spring Boot 3.2的一部分。这个注解允许在Spring内部配置为使用特殊类型的线程(通过属性)时创建bean。

如往常一样,文章的源代码可在GitHub上找到。