Skip to content

Commit 3793fc1

Browse files
garyrussellartembilan
authored andcommitted
GH-1136: Support Meta Annotations with AliasFor
Resolves #1136 Note that this is a minimal implementation that avoids major refactoring of the BPP. Repeatable user meta-annotatiions are not supported. In a future release we should perform that refactoring as well as supporting `@Repeatable` user annotations. Also restore the `stop()` with finally to fix `EnableRabbitTests.testProperShutdownOnException()` which took 30 seconds to run after the finally was removed by c1e3179 * Increase search scope
1 parent 1b173a4 commit 3793fc1

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/annotation/RabbitListenerAnnotationBeanPostProcessor.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
import org.springframework.context.expression.StandardBeanExpressionResolver;
7070
import org.springframework.core.Ordered;
7171
import org.springframework.core.annotation.AnnotationUtils;
72+
import org.springframework.core.annotation.MergedAnnotation;
73+
import org.springframework.core.annotation.MergedAnnotations;
74+
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
7275
import org.springframework.core.convert.ConversionService;
7376
import org.springframework.core.convert.converter.Converter;
7477
import org.springframework.core.convert.support.DefaultConversionService;
@@ -421,9 +424,30 @@ private Method checkProxy(Method methodArg, Object bean) {
421424
return method;
422425
}
423426

424-
protected void processListener(MethodRabbitListenerEndpoint endpoint, RabbitListener rabbitListener, Object bean,
427+
protected void processListener(MethodRabbitListenerEndpoint endpoint, RabbitListener rabbitListenerArg, Object bean,
425428
Object target, String beanName) {
426429

430+
RabbitListener rabbitListener = rabbitListenerArg;
431+
MergedAnnotation<RabbitListener> mergedAnnotation = MergedAnnotation.missing();
432+
/*
433+
* Synthesize the actual annotation to handle meta-annotations and aliasing. Note
434+
* that only single @RabbitListener annotations can be meta-annotated.
435+
*/
436+
if (endpoint instanceof MultiMethodRabbitListenerEndpoint) {
437+
if (AnnotationUtils.findAnnotation((Class<?>) target, RabbitListeners.class) == null) {
438+
mergedAnnotation = MergedAnnotations.from((Class<?>) target, SearchStrategy.TYPE_HIERARCHY)
439+
.get(RabbitListener.class);
440+
}
441+
}
442+
else {
443+
if (AnnotationUtils.findAnnotation(endpoint.getMethod(), RabbitListeners.class) == null) {
444+
mergedAnnotation = MergedAnnotations.from(endpoint.getMethod(), SearchStrategy.TYPE_HIERARCHY)
445+
.get(RabbitListener.class);
446+
}
447+
}
448+
if (!MergedAnnotation.missing().equals(mergedAnnotation)) {
449+
rabbitListener = mergedAnnotation.synthesize();
450+
}
427451
endpoint.setBean(bean);
428452
endpoint.setMessageHandlerMethodFactory(this.messageHandlerMethodFactory);
429453
endpoint.setId(getEndpointId(rabbitListener));

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/AbstractMessageListenerContainer.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,16 @@ public void stop() {
13411341
}
13421342
}
13431343

1344+
@Override
1345+
public void stop(Runnable callback) {
1346+
try {
1347+
stop();
1348+
}
1349+
finally {
1350+
callback.run();
1351+
}
1352+
}
1353+
13441354
/**
13451355
* This method is invoked when the container is stopping.
13461356
*/

spring-rabbit/src/test/java/org/springframework/amqp/rabbit/annotation/RabbitListenerAnnotationBeanPostProcessorTests.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.springframework.context.annotation.Configuration;
5656
import org.springframework.context.annotation.PropertySource;
5757
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
58+
import org.springframework.core.annotation.AliasFor;
5859
import org.springframework.stereotype.Component;
5960

6061
/**
@@ -124,7 +125,10 @@ public void metaAnnotationIsDiscovered() {
124125
RabbitListenerContainerTestFactory factory = context.getBean(RabbitListenerContainerTestFactory.class);
125126
assertThat(factory.getListenerContainers().size()).as("one container should have been registered").isEqualTo(1);
126127
RabbitListenerEndpoint endpoint = factory.getListenerContainers().get(0).getEndpoint();
127-
assertThat(((AbstractRabbitListenerEndpoint) endpoint).getQueueNames().iterator().next()).isEqualTo("metaTestQueue");
128+
assertThat(((AbstractRabbitListenerEndpoint) endpoint).getQueueNames()
129+
.iterator()
130+
.next())
131+
.isEqualTo("metaTestQueue");
128132

129133
context.close();
130134
}
@@ -330,16 +334,20 @@ public void handleIt(String body) {
330334
@Component
331335
static class MetaAnnotationTestBean {
332336

333-
@FooListener
337+
@FooListener("metaTestQueue")
334338
public void handleIt(String body) {
335339
}
336340
}
337341

338342

339-
@RabbitListener(queues = "metaTestQueue")
343+
@RabbitListener
340344
@Target(ElementType.METHOD)
341345
@Retention(RetentionPolicy.RUNTIME)
342346
static @interface FooListener {
347+
348+
@AliasFor(annotation = RabbitListener.class, attribute = "queues")
349+
String[] value() default {};
350+
343351
}
344352

345353
@Component

0 commit comments

Comments
 (0)