Skip to content

Commit eb928ce

Browse files
committed
Reliably detect event listener conditions on proxied beans
Issue: SPR-15678
1 parent a6d616d commit eb928ce

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.springframework.expression.EvaluationContext;
3939
import org.springframework.lang.Nullable;
4040
import org.springframework.util.Assert;
41+
import org.springframework.util.ClassUtils;
4142
import org.springframework.util.ObjectUtils;
4243
import org.springframework.util.ReflectionUtils;
4344
import org.springframework.util.StringUtils;
@@ -91,7 +92,9 @@ public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, M
9192
this.targetClass = targetClass;
9293
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
9394

94-
EventListener ann = AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
95+
Method targetMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
96+
EventListener ann = AnnotatedElementUtils.findMergedAnnotation(targetMethod, EventListener.class);
97+
9598
this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
9699
this.condition = (ann != null ? ann.condition() : null);
97100
this.order = resolveOrder(method);

spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
import org.springframework.scheduling.annotation.EnableAsync;
6464
import org.springframework.stereotype.Component;
6565
import org.springframework.util.Assert;
66+
import org.springframework.validation.annotation.Validated;
67+
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
6668

6769
import static org.hamcrest.Matchers.*;
6870
import static org.junit.Assert.*;
@@ -491,10 +493,20 @@ public void listenerWithResolvableTypeEventWrongGeneric() {
491493

492494
@Test
493495
public void conditionMatch() {
496+
validateConditionMatch(ConditionalEventListener.class);
497+
}
498+
499+
@Test
500+
public void conditionMatchWithProxy() {
501+
validateConditionMatch(ConditionalEventListener.class, MethodValidationPostProcessor.class);
502+
}
503+
504+
private void validateConditionMatch(Class<?>... classes) {
494505
long timestamp = System.currentTimeMillis();
495-
load(ConditionalEventListener.class);
506+
load(classes);
496507
TestEvent event = new TestEvent(this, "OK");
497-
TestEventListener listener = this.context.getBean(ConditionalEventListener.class);
508+
509+
ConditionalEventInterface listener = this.context.getBean(ConditionalEventInterface.class);
498510
this.eventCollector.assertNoEventReceived(listener);
499511

500512
this.context.publishEvent(event);
@@ -505,6 +517,9 @@ public void conditionMatch() {
505517
this.eventCollector.assertEvent(listener, event, "OK");
506518
this.eventCollector.assertTotalEventsCount(2);
507519

520+
this.context.publishEvent("NOT OK");
521+
this.eventCollector.assertTotalEventsCount(2);
522+
508523
this.context.publishEvent(timestamp);
509524
this.eventCollector.assertEvent(listener, event, "OK", timestamp);
510525
this.eventCollector.assertTotalEventsCount(3);
@@ -896,8 +911,21 @@ public void handleString(GenericEventPojo<String> value) {
896911
}
897912

898913

914+
interface ConditionalEventInterface extends Identifiable {
915+
916+
void handle(TestEvent event);
917+
918+
void handleString(String payload);
919+
920+
void handleTimestamp(Long timestamp);
921+
922+
void handleRatio(Double ratio);
923+
}
924+
925+
899926
@Component
900-
static class ConditionalEventListener extends TestEventListener {
927+
@Validated
928+
static class ConditionalEventListener extends TestEventListener implements ConditionalEventInterface {
901929

902930
@EventListener(condition = "'OK'.equals(#root.event.msg)")
903931
@Override

0 commit comments

Comments
 (0)