diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/AnnotationAsyncExecutionInterceptorTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/AnnotationAsyncExecutionInterceptorTests.java index b0ddea9e16..b698b4fbe1 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/annotation/AnnotationAsyncExecutionInterceptorTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/AnnotationAsyncExecutionInterceptorTests.java @@ -16,6 +16,9 @@ package org.springframework.scheduling.annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + import org.junit.Test; import static org.hamcrest.CoreMatchers.*; @@ -33,21 +36,29 @@ public class AnnotationAsyncExecutionInterceptorTests { @SuppressWarnings("unused") public void testGetExecutorQualifier() throws SecurityException, NoSuchMethodException { AnnotationAsyncExecutionInterceptor i = new AnnotationAsyncExecutionInterceptor(null); - { + { // method level class C { @Async("qMethod") void m() { } } assertThat(i.getExecutorQualifier(C.class.getDeclaredMethod("m")), is("qMethod")); } - { + { // class level @Async("qClass") class C { void m() { } } assertThat(i.getExecutorQualifier(C.class.getDeclaredMethod("m")), is("qClass")); } - { + { // method and class level -> method value overrides @Async("qClass") class C { @Async("qMethod") void m() { } } assertThat(i.getExecutorQualifier(C.class.getDeclaredMethod("m")), is("qMethod")); } - { + { // method and class level -> method value, even if empty, overrides @Async("qClass") class C { @Async void m() { } } assertThat(i.getExecutorQualifier(C.class.getDeclaredMethod("m")), is("")); } + { // meta annotation with qualifier + @MyAsync class C { void m() { } } + assertThat(i.getExecutorQualifier(C.class.getDeclaredMethod("m")), is("qMeta")); + } } + + @Async("qMeta") + @Retention(RetentionPolicy.RUNTIME) + @interface MyAsync { } }