mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Only configure WebFlux blocking executor when using virtual threads
Fixes gh-39469
This commit is contained in:
parent
720e9cef16
commit
256f9fe83a
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -34,6 +34,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
|||||||
import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration;
|
import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
|
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||||
|
import org.springframework.boot.autoconfigure.thread.Threading;
|
||||||
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
|
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
|
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
|
||||||
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
|
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
|
||||||
@ -55,6 +56,7 @@ import org.springframework.context.annotation.Import;
|
|||||||
import org.springframework.context.annotation.ImportRuntimeHints;
|
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.task.AsyncTaskExecutor;
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
import org.springframework.format.FormatterRegistry;
|
import org.springframework.format.FormatterRegistry;
|
||||||
import org.springframework.format.support.FormattingConversionService;
|
import org.springframework.format.support.FormattingConversionService;
|
||||||
@ -149,6 +151,8 @@ public class WebFluxAutoConfiguration {
|
|||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(WebFluxConfig.class);
|
private static final Log logger = LogFactory.getLog(WebFluxConfig.class);
|
||||||
|
|
||||||
|
private final Environment environment;
|
||||||
|
|
||||||
private final Resources resourceProperties;
|
private final Resources resourceProperties;
|
||||||
|
|
||||||
private final WebFluxProperties webFluxProperties;
|
private final WebFluxProperties webFluxProperties;
|
||||||
@ -163,11 +167,12 @@ public class WebFluxAutoConfiguration {
|
|||||||
|
|
||||||
private final ObjectProvider<ViewResolver> viewResolvers;
|
private final ObjectProvider<ViewResolver> viewResolvers;
|
||||||
|
|
||||||
public WebFluxConfig(WebProperties webProperties, WebFluxProperties webFluxProperties,
|
public WebFluxConfig(Environment environment, WebProperties webProperties, WebFluxProperties webFluxProperties,
|
||||||
ListableBeanFactory beanFactory, ObjectProvider<HandlerMethodArgumentResolver> resolvers,
|
ListableBeanFactory beanFactory, ObjectProvider<HandlerMethodArgumentResolver> resolvers,
|
||||||
ObjectProvider<CodecCustomizer> codecCustomizers,
|
ObjectProvider<CodecCustomizer> codecCustomizers,
|
||||||
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizer,
|
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizer,
|
||||||
ObjectProvider<ViewResolver> viewResolvers) {
|
ObjectProvider<ViewResolver> viewResolvers) {
|
||||||
|
this.environment = environment;
|
||||||
this.resourceProperties = webProperties.getResources();
|
this.resourceProperties = webProperties.getResources();
|
||||||
this.webFluxProperties = webFluxProperties;
|
this.webFluxProperties = webFluxProperties;
|
||||||
this.beanFactory = beanFactory;
|
this.beanFactory = beanFactory;
|
||||||
@ -189,7 +194,8 @@ public class WebFluxAutoConfiguration {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configureBlockingExecution(BlockingExecutionConfigurer configurer) {
|
public void configureBlockingExecution(BlockingExecutionConfigurer configurer) {
|
||||||
if (this.beanFactory.containsBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)) {
|
if (Threading.VIRTUAL.isActive(this.environment) && this.beanFactory
|
||||||
|
.containsBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)) {
|
||||||
Object taskExecutor = this.beanFactory
|
Object taskExecutor = this.beanFactory
|
||||||
.getBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME);
|
.getBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME);
|
||||||
if (taskExecutor instanceof AsyncTaskExecutor asyncTaskExecutor) {
|
if (taskExecutor instanceof AsyncTaskExecutor asyncTaskExecutor) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -39,6 +39,8 @@ import org.aspectj.lang.annotation.Aspect;
|
|||||||
import org.assertj.core.api.Assertions;
|
import org.assertj.core.api.Assertions;
|
||||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.condition.EnabledForJreRange;
|
||||||
|
import org.junit.jupiter.api.condition.JRE;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
@ -687,8 +689,20 @@ class WebFluxAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void asyncTaskExecutorWithApplicationTaskExecutor() {
|
void asyncTaskExecutorWithPlatformThreadsAndApplicationTaskExecutor() {
|
||||||
this.contextRunner.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
this.contextRunner.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
||||||
|
.run((context) -> {
|
||||||
|
assertThat(context).hasSingleBean(AsyncTaskExecutor.class);
|
||||||
|
assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor")
|
||||||
|
.isNull();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnabledForJreRange(min = JRE.JAVA_21)
|
||||||
|
void asyncTaskExecutorWithVirtualThreadsAndApplicationTaskExecutor() {
|
||||||
|
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true")
|
||||||
|
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(AsyncTaskExecutor.class);
|
assertThat(context).hasSingleBean(AsyncTaskExecutor.class);
|
||||||
assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor")
|
assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor")
|
||||||
@ -697,8 +711,10 @@ class WebFluxAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void asyncTaskExecutorWithNonMatchApplicationTaskExecutorBean() {
|
@EnabledForJreRange(min = JRE.JAVA_21)
|
||||||
this.contextRunner.withUserConfiguration(CustomApplicationTaskExecutorConfig.class)
|
void asyncTaskExecutorWithVirtualThreadsAndNonMatchApplicationTaskExecutorBean() {
|
||||||
|
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true")
|
||||||
|
.withUserConfiguration(CustomApplicationTaskExecutorConfig.class)
|
||||||
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).doesNotHaveBean(AsyncTaskExecutor.class);
|
assertThat(context).doesNotHaveBean(AsyncTaskExecutor.class);
|
||||||
@ -708,8 +724,10 @@ class WebFluxAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void asyncTaskExecutorWithWebFluxConfigurerCanOverrideExecutor() {
|
@EnabledForJreRange(min = JRE.JAVA_21)
|
||||||
this.contextRunner.withUserConfiguration(CustomAsyncTaskExecutorConfigurer.class)
|
void asyncTaskExecutorWithVirtualThreadsAndWebFluxConfigurerCanOverrideExecutor() {
|
||||||
|
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true")
|
||||||
|
.withUserConfiguration(CustomAsyncTaskExecutorConfigurer.class)
|
||||||
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
||||||
.run((context) -> assertThat(context.getBean(RequestMappingHandlerAdapter.class))
|
.run((context) -> assertThat(context.getBean(RequestMappingHandlerAdapter.class))
|
||||||
.extracting("scheduler.executor")
|
.extracting("scheduler.executor")
|
||||||
@ -717,13 +735,15 @@ class WebFluxAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void asyncTaskExecutorWithCustomNonApplicationTaskExecutor() {
|
@EnabledForJreRange(min = JRE.JAVA_21)
|
||||||
this.contextRunner.withUserConfiguration(CustomAsyncTaskExecutorConfig.class)
|
void asyncTaskExecutorWithVirtualThreadsAndCustomNonApplicationTaskExecutor() {
|
||||||
|
this.contextRunner.withPropertyValues("spring.threads.virtual.enabled=true")
|
||||||
|
.withUserConfiguration(CustomAsyncTaskExecutorConfig.class)
|
||||||
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
.withConfiguration(AutoConfigurations.of(TaskExecutionAutoConfiguration.class))
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(AsyncTaskExecutor.class);
|
assertThat(context).hasSingleBean(AsyncTaskExecutor.class);
|
||||||
assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor")
|
assertThat(context.getBean(RequestMappingHandlerAdapter.class)).extracting("scheduler.executor")
|
||||||
.isNotSameAs(context.getBean("customTaskExecutor"));
|
.isNull();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user