diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java index 51b76a23b1..26b66a2b8a 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java @@ -41,6 +41,7 @@ import org.springframework.core.task.support.TaskExecutorAdapter; import org.springframework.lang.Nullable; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; +import org.springframework.util.StringValueResolver; import org.springframework.util.function.SingletonSupplier; /** @@ -56,6 +57,7 @@ import org.springframework.util.function.SingletonSupplier; * @author Chris Beams * @author Juergen Hoeller * @author Stephane Nicoll + * @author He Bo * @since 3.1.2 */ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { @@ -80,6 +82,8 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { @Nullable private BeanFactory beanFactory; + @Nullable + private StringValueResolver stringValueResolver; /** * Create a new instance with a default {@link AsyncUncaughtExceptionHandler}. @@ -150,6 +154,9 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { @Override public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; + if (beanFactory instanceof ConfigurableBeanFactory configurableBeanFactory) { + this.stringValueResolver = new EmbeddedValueResolver(configurableBeanFactory); + } } @@ -163,6 +170,9 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { if (executor == null) { Executor targetExecutor; String qualifier = getExecutorQualifier(method); + if (this.stringValueResolver != null && StringUtils.hasLength(qualifier)) { + qualifier = this.stringValueResolver.resolveStringValue(qualifier); + } if (StringUtils.hasLength(qualifier)) { targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier); } @@ -206,10 +216,6 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() + " to access qualified executor '" + qualifier + "'"); } - if (beanFactory instanceof ConfigurableBeanFactory configurableBeanFactory) { - EmbeddedValueResolver embeddedValueResolver = new EmbeddedValueResolver(configurableBeanFactory); - qualifier = embeddedValueResolver.resolveStringValue(qualifier); - } return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier); } diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java index f19c945b08..b2a1e1140e 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java @@ -146,6 +146,9 @@ public class EnableAsyncTests { Future workerThread2 = asyncBean.myWork2(); assertThat(workerThread2.get().getName()).startsWith("myExecutor2-"); + + Future workerThread3 = asyncBean.defaultExecutor(); + assertThat(workerThread3.get().getName()).startsWith("SimpleAsyncTaskExecutor"); } finally { System.clearProperty("myExecutor"); @@ -382,6 +385,11 @@ public class EnableAsyncTests { public Future myWork2() { return new AsyncResult<>(Thread.currentThread()); } + + @Async("${my.app.targetExecutor:}") + public Future defaultExecutor() { + return new AsyncResult<>(Thread.currentThread()); + } }