From 6fc4898a1b5d663c6948d6c66291b34de134a246 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 12 Aug 2023 11:19:21 +0200 Subject: [PATCH 1/2] Find TransactionalEventListener annotation on target method Closes gh-31034 --- ...ionalApplicationListenerMethodAdapter.java | 12 ++++---- .../TransactionalEventListenerTests.java | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java index ce39e136c1a..7811aeda7f4 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java +++ b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,13 +63,13 @@ public class TransactionalApplicationListenerMethodAdapter extends ApplicationLi */ public TransactionalApplicationListenerMethodAdapter(String beanName, Class targetClass, Method method) { super(beanName, targetClass, method); - TransactionalEventListener ann = - AnnotatedElementUtils.findMergedAnnotation(method, TransactionalEventListener.class); - if (ann == null) { + TransactionalEventListener eventAnn = + AnnotatedElementUtils.findMergedAnnotation(getTargetMethod(), TransactionalEventListener.class); + if (eventAnn == null) { throw new IllegalStateException("No TransactionalEventListener annotation found on method: " + method); } - this.annotation = ann; - this.transactionPhase = ann.phase(); + this.annotation = eventAnn; + this.transactionPhase = eventAnn.phase(); } diff --git a/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java b/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java index ff215f05133..a8091e0ce76 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java @@ -156,6 +156,17 @@ public class TransactionalEventListenerTests { getEventCollector().assertNoEventReceived(); } + @Test + public void afterCommitWithTransactionalComponentListenerWithInterfaceProxy() { + load(TransactionalComponentTestListenerWithInterface.class); + this.transactionTemplate.execute(status -> { + getContext().publishEvent("SKIP"); + getEventCollector().assertNoEventReceived(); + return null; + }); + getEventCollector().assertNoEventReceived(); + } + @Test public void afterRollback() { load(AfterCompletionExplicitTestListener.class); @@ -525,6 +536,25 @@ public class TransactionalEventListenerTests { } + interface TransactionalComponentTestInterface { + + void handleAfterCommit(String data); + } + + + @Transactional + @Component + static class TransactionalComponentTestListenerWithInterface extends BaseTransactionalTestListener implements + TransactionalComponentTestInterface { + + @TransactionalEventListener(condition = "!'SKIP'.equals(#data)") + @Override + public void handleAfterCommit(String data) { + handleEvent(EventCollector.AFTER_COMMIT, data); + } + } + + @Component static class BeforeCommitTestListener extends BaseTransactionalTestListener { From d781f299c0a38ed9a29001920e811165e2054773 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 12 Aug 2023 11:34:25 +0200 Subject: [PATCH 2/2] Use extracted attributes instead of annotation access See gh-31034 --- .../TransactionalApplicationListenerMethodAdapter.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java index 7811aeda7f4..b12aff8e17b 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java +++ b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java @@ -48,10 +48,10 @@ import org.springframework.util.Assert; public class TransactionalApplicationListenerMethodAdapter extends ApplicationListenerMethodAdapter implements TransactionalApplicationListener { - private final TransactionalEventListener annotation; - private final TransactionPhase transactionPhase; + private final boolean fallbackExecution; + private final List callbacks = new CopyOnWriteArrayList<>(); @@ -68,8 +68,8 @@ public class TransactionalApplicationListenerMethodAdapter extends ApplicationLi if (eventAnn == null) { throw new IllegalStateException("No TransactionalEventListener annotation found on method: " + method); } - this.annotation = eventAnn; this.transactionPhase = eventAnn.phase(); + this.fallbackExecution = eventAnn.fallbackExecution(); } @@ -92,8 +92,8 @@ public class TransactionalApplicationListenerMethodAdapter extends ApplicationLi TransactionSynchronizationManager.registerSynchronization( new TransactionalApplicationListenerSynchronization<>(event, this, this.callbacks)); } - else if (this.annotation.fallbackExecution()) { - if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK && logger.isWarnEnabled()) { + else if (this.fallbackExecution) { + if (getTransactionPhase() == TransactionPhase.AFTER_ROLLBACK && logger.isWarnEnabled()) { logger.warn("Processing " + event + " as a fallback execution on AFTER_ROLLBACK phase"); } processEvent(event);