Skip to content

Commit be8224a

Browse files
committed
Polish contribution
See gh-27818
1 parent 01214b3 commit be8224a

File tree

3 files changed

+32
-33
lines changed

3 files changed

+32
-33
lines changed

spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import org.springframework.lang.Nullable;
4444
import org.springframework.util.ReflectionUtils;
4545
import org.springframework.util.StringUtils;
46-
import org.springframework.util.StringValueResolver;
4746
import org.springframework.util.concurrent.ListenableFuture;
4847
import org.springframework.util.function.SingletonSupplier;
4948

@@ -212,9 +211,8 @@ protected Executor findQualifiedExecutor(@Nullable BeanFactory beanFactory, Stri
212211
" to access qualified executor '" + qualifier + "'");
213212
}
214213
if (beanFactory instanceof ConfigurableBeanFactory configurableBeanFactory) {
215-
StringValueResolver embeddedValueResolver = new EmbeddedValueResolver(configurableBeanFactory);
216-
String resolvedValue = embeddedValueResolver.resolveStringValue(qualifier);
217-
qualifier = resolvedValue != null ? resolvedValue : "";
214+
EmbeddedValueResolver embeddedValueResolver = new EmbeddedValueResolver(configurableBeanFactory);
215+
qualifier = embeddedValueResolver.resolveStringValue(qualifier);
218216
}
219217
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
220218
}

spring-context/src/main/java/org/springframework/scheduling/annotation/Async.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424

2525
/**
2626
* Annotation that marks a method as a candidate for <i>asynchronous</i> execution.
27-
* Can also be used at the type level, in which case all of the type's methods are
27+
*
28+
* <p>Can also be used at the type level, in which case all of the type's methods are
2829
* considered as asynchronous. Note, however, that {@code @Async} is not supported
2930
* on methods declared within a
3031
* {@link org.springframework.context.annotation.Configuration @Configuration} class.
@@ -41,7 +42,7 @@
4142
* {@code Future} that can be used to track the result of the asynchronous method
4243
* execution. However, since the target method needs to implement the same signature,
4344
* it will have to return a temporary {@code Future} handle that just passes a value
44-
* through: e.g. Spring's {@link AsyncResult}, EJB 3.1's {@link jakarta.ejb.AsyncResult},
45+
* through: for example, Spring's {@link AsyncResult}, EJB 3.1's {@link jakarta.ejb.AsyncResult},
4546
* or {@link java.util.concurrent.CompletableFuture#completedFuture(Object)}.
4647
*
4748
* @author Juergen Hoeller
@@ -57,16 +58,18 @@
5758

5859
/**
5960
* A qualifier value for the specified asynchronous operation(s).
60-
* <p>The value support expression such as <code>#{systemProperties.myExecutor}</code>
61-
* or property placeholder such as <code>${my.app.myExecutor}</code>.
6261
* <p>May be used to determine the target executor to be used when executing
6362
* the asynchronous operation(s), matching the qualifier value (or the bean
6463
* name) of a specific {@link java.util.concurrent.Executor Executor} or
6564
* {@link org.springframework.core.task.TaskExecutor TaskExecutor}
6665
* bean definition.
67-
* <p>When specified on a class-level {@code @Async} annotation, indicates that the
66+
* <p>When specified in a class-level {@code @Async} annotation, indicates that the
6867
* given executor should be used for all methods within the class. Method-level use
69-
* of {@code Async#value} always overrides any value set at the class level.
68+
* of {@code Async#value} always overrides any qualifier value configured at
69+
* the class level.
70+
* <p>The qualifier value will be resolved dynamically if supplied as a SpEL
71+
* expression (for example, {@code "#{environment['myExecutor']}"}) or a
72+
* property placeholder (for example, {@code "${my.app.myExecutor}"}).
7073
* @since 3.1.2
7174
*/
7275
String value() default "";

spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.lang.annotation.RetentionPolicy;
2222
import java.lang.annotation.Target;
2323
import java.lang.reflect.Method;
24-
import java.util.Properties;
2524
import java.util.concurrent.ExecutionException;
2625
import java.util.concurrent.Executor;
2726
import java.util.concurrent.Executors;
@@ -42,13 +41,13 @@
4241
import org.springframework.beans.factory.UnsatisfiedDependencyException;
4342
import org.springframework.beans.factory.annotation.Qualifier;
4443
import org.springframework.beans.factory.config.BeanPostProcessor;
44+
import org.springframework.context.ConfigurableApplicationContext;
4545
import org.springframework.context.annotation.AdviceMode;
4646
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
4747
import org.springframework.context.annotation.Bean;
4848
import org.springframework.context.annotation.Configuration;
4949
import org.springframework.context.annotation.Import;
5050
import org.springframework.context.annotation.Lazy;
51-
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
5251
import org.springframework.core.Ordered;
5352
import org.springframework.lang.Nullable;
5453
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
@@ -133,26 +132,25 @@ public void withAsyncBeanWithExecutorQualifiedByName() throws ExecutionException
133132
}
134133

135134
@Test
136-
public void withAsyncBeanWithExecutorQualifiedByExpression() throws ExecutionException, InterruptedException {
137-
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
138-
System.getProperties().put("myExecutor", "myExecutor1");
139-
PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
140-
placeholderConfigurer.setProperties(new Properties() {{
141-
put("my.app.myExecutor", "myExecutor2");
142-
}});
143-
placeholderConfigurer.postProcessBeanFactory(context.getBeanFactory());
135+
public void withAsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder() throws Exception {
136+
System.setProperty("myExecutor", "myExecutor1");
137+
System.setProperty("my.app.myExecutor", "myExecutor2");
144138

145-
context.register(AsyncWithExecutorQualifiedByExpressionConfig.class);
146-
context.refresh();
139+
Class<?> configClass = AsyncWithExecutorQualifiedByExpressionConfig.class;
140+
try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(configClass)) {
141+
AsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder asyncBean =
142+
context.getBean(AsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder.class);
147143

148-
AsyncBeanWithExecutorQualifiedByExpression asyncBean = context.getBean(AsyncBeanWithExecutorQualifiedByExpression.class);
149-
Future<Thread> workerThread1 = asyncBean.myWork1();
150-
assertThat(workerThread1.get().getName()).doesNotStartWith("myExecutor2-").startsWith("myExecutor1-");
144+
Future<Thread> workerThread1 = asyncBean.myWork1();
145+
assertThat(workerThread1.get().getName()).startsWith("myExecutor1-");
151146

152-
Future<Thread> workerThread2 = asyncBean.myWork2();
153-
assertThat(workerThread2.get().getName()).startsWith("myExecutor2-");
154-
155-
context.close();
147+
Future<Thread> workerThread2 = asyncBean.myWork2();
148+
assertThat(workerThread2.get().getName()).startsWith("myExecutor2-");
149+
}
150+
finally {
151+
System.clearProperty("myExecutor");
152+
System.clearProperty("my.app.myExecutor");
153+
}
156154
}
157155

158156
@Test
@@ -371,9 +369,9 @@ public Future<Thread> work3() {
371369
}
372370
}
373371

374-
static class AsyncBeanWithExecutorQualifiedByExpression {
372+
static class AsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder {
375373

376-
@Async("#{systemProperties.myExecutor}")
374+
@Async("#{environment['myExecutor']}")
377375
public Future<Thread> myWork1() {
378376
return new AsyncResult<>(Thread.currentThread());
379377
}
@@ -518,8 +516,8 @@ public Executor otherExecutor() {
518516
static class AsyncWithExecutorQualifiedByExpressionConfig {
519517

520518
@Bean
521-
public AsyncBeanWithExecutorQualifiedByExpression asyncBean() {
522-
return new AsyncBeanWithExecutorQualifiedByExpression();
519+
public AsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder asyncBean() {
520+
return new AsyncBeanWithExecutorQualifiedByExpressionOrPlaceholder();
523521
}
524522

525523
@Bean

0 commit comments

Comments
 (0)