1515 */
1616package org .springframework .modulith .events .support ;
1717
18+ import java .lang .reflect .Method ;
1819import java .time .Duration ;
1920import java .util .Collection ;
2021import java .util .List ;
4546import org .springframework .transaction .event .TransactionPhase ;
4647import org .springframework .transaction .event .TransactionalApplicationListener ;
4748import org .springframework .util .Assert ;
49+ import org .springframework .util .ReflectionUtils ;
4850
4951/**
5052 * An {@link org.springframework.context.event.ApplicationEventMulticaster} to register {@link EventPublication}s in an
@@ -61,12 +63,23 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
6163 implements IncompleteEventPublications , SmartInitializingSingleton {
6264
6365 private static final Logger LOGGER = LoggerFactory .getLogger (PersistentApplicationEventMulticaster .class );
66+ private static final Method LEGACY_SHOULD_HANDLE = ReflectionUtils .findMethod (ApplicationListenerMethodAdapter .class ,
67+ "shouldHandle" , ApplicationEvent .class , Object [].class );
68+ private static final Method SHOULD_HANDLE = ReflectionUtils .findMethod (ApplicationListenerMethodAdapter .class ,
69+ "shouldHandle" , ApplicationEvent .class );
6470
6571 static final String REPUBLISH_ON_RESTART = "spring.modulith.republish-outstanding-events-on-restart" ;
6672
6773 private final @ NonNull Supplier <EventPublicationRegistry > registry ;
6874 private final @ NonNull Supplier <Environment > environment ;
6975
76+ static {
77+
78+ if (SHOULD_HANDLE == null ) {
79+ ReflectionUtils .makeAccessible (LEGACY_SHOULD_HANDLE );
80+ }
81+ }
82+
7083 /**
7184 * Creates a new {@link PersistentApplicationEventMulticaster} for the given {@link EventPublicationRegistry}.
7285 *
@@ -222,9 +235,7 @@ private static Object getEventToPersist(ApplicationEvent event) {
222235 private static boolean matches (ApplicationEvent event , Object payload , ApplicationListener <?> listener ) {
223236
224237 // Verify general listener matching by eagerly evaluating the condition
225- if (ApplicationListenerMethodAdapter .class .isInstance (listener )
226- && !((ApplicationListenerMethodAdapter ) listener ).shouldHandle (event )) {
227-
238+ if (!invokeShouldHandle (listener , event , payload )) {
228239 return false ;
229240 }
230241
@@ -233,6 +244,27 @@ private static boolean matches(ApplicationEvent event, Object payload, Applicati
233244 : true ;
234245 }
235246
247+ /**
248+ * Invokes {@link ApplicationListenerMethodAdapter#shouldHandle(ApplicationEvent)} in case the given candidate is one
249+ * in the first place but falls back to call {@code shouldHandle(ApplicationEvent, Object)} reflectively as fallback.
250+ *
251+ * @param candidate the listener to test, must not be {@literal null}.
252+ * @param event the event to publish, must not be {@literal null}.
253+ * @param payload the actual payload, must not be {@literal null}.
254+ * @return whether the event should be handled by the given candidate.
255+ */
256+ @ SuppressWarnings ("null" )
257+ private static boolean invokeShouldHandle (ApplicationListener <?> candidate , ApplicationEvent event , Object payload ) {
258+
259+ if (!(candidate instanceof ApplicationListenerMethodAdapter listener )) {
260+ return true ;
261+ }
262+
263+ return SHOULD_HANDLE != null
264+ ? listener .shouldHandle (event )
265+ : (boolean ) ReflectionUtils .invokeMethod (LEGACY_SHOULD_HANDLE , candidate , event , new Object [] { payload });
266+ }
267+
236268 private static String getConfirmationMessage (Collection <?> publications ) {
237269
238270 var size = publications .size ();
0 commit comments