1515 */
1616package org .springframework .modulith .events .support ;
1717
18+ import java .lang .reflect .Method ;
1819import java .util .Collection ;
1920import java .util .List ;
2021import java .util .function .Consumer ;
2930import org .springframework .context .PayloadApplicationEvent ;
3031import org .springframework .context .event .AbstractApplicationEventMulticaster ;
3132import org .springframework .context .event .ApplicationEventMulticaster ;
33+ import org .springframework .context .event .ApplicationListenerMethodAdapter ;
3234import org .springframework .core .ResolvableType ;
3335import org .springframework .core .annotation .AnnotationAwareOrderComparator ;
3436import org .springframework .core .env .Environment ;
3537import org .springframework .lang .NonNull ;
38+ import org .springframework .lang .Nullable ;
3639import org .springframework .modulith .events .core .EventPublication ;
3740import org .springframework .modulith .events .core .EventPublicationRegistry ;
3841import org .springframework .modulith .events .core .PublicationTargetIdentifier ;
3942import org .springframework .transaction .event .TransactionPhase ;
4043import org .springframework .transaction .event .TransactionalApplicationListener ;
4144import org .springframework .transaction .event .TransactionalEventListener ;
4245import org .springframework .util .Assert ;
46+ import org .springframework .util .ReflectionUtils ;
4347
4448/**
4549 * An {@link ApplicationEventMulticaster} to register {@link EventPublication}s in an {@link EventPublicationRegistry}
@@ -56,11 +60,17 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
5660 implements SmartInitializingSingleton {
5761
5862 private static final Logger LOGGER = LoggerFactory .getLogger (PersistentApplicationEventMulticaster .class );
63+ private static final Method SUPPORTS_METHOD = ReflectionUtils .findMethod (ApplicationListenerMethodAdapter .class ,
64+ "shouldHandle" , ApplicationEvent .class , Object [].class );
5965 static final String REPUBLISH_ON_RESTART = "spring.modulith.republish-outstanding-events-on-restart" ;
6066
6167 private final @ NonNull Supplier <EventPublicationRegistry > registry ;
6268 private final @ NonNull Supplier <Environment > environment ;
6369
70+ static {
71+ ReflectionUtils .makeAccessible (SUPPORTS_METHOD );
72+ }
73+
6474 /**
6575 * Creates a new {@link PersistentApplicationEventMulticaster} for the given {@link EventPublicationRegistry}.
6676 *
@@ -92,7 +102,7 @@ public void multicastEvent(ApplicationEvent event) {
92102 */
93103 @ Override
94104 @ SuppressWarnings ({ "unchecked" , "rawtypes" })
95- public void multicastEvent (ApplicationEvent event , ResolvableType eventType ) {
105+ public void multicastEvent (ApplicationEvent event , @ Nullable ResolvableType eventType ) {
96106
97107 var type = eventType == null ? ResolvableType .forInstance (event ) : eventType ;
98108 var listeners = getApplicationListeners (event , type );
@@ -109,6 +119,22 @@ public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
109119 }
110120 }
111121
122+ /*
123+ * (non-Javadoc)
124+ * @see org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
125+ */
126+ @ Override
127+ protected Collection <ApplicationListener <?>> getApplicationListeners (ApplicationEvent event ,
128+ ResolvableType eventType ) {
129+
130+ Object eventToPersist = getEventToPersist (event );
131+
132+ return super .getApplicationListeners (event , eventType )
133+ .stream ()
134+ .filter (it -> matches (event , eventToPersist , it ))
135+ .toList ();
136+ }
137+
112138 /*
113139 * (non-Javadoc)
114140 * @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated()
@@ -169,6 +195,18 @@ private static Object getEventToPersist(ApplicationEvent event) {
169195 : event ;
170196 }
171197
198+ @ SuppressWarnings ("null" )
199+ private static boolean matches (ApplicationEvent event , Object payload , ApplicationListener <?> listener ) {
200+
201+ // Verify general listener matching by eagerly evaluating the condition
202+ if (!ApplicationListenerMethodAdapter .class .isInstance (listener )) {
203+ return true ;
204+ }
205+
206+ return (boolean ) ReflectionUtils .invokeMethod (SUPPORTS_METHOD , listener , event ,
207+ new Object [] { payload });
208+ }
209+
172210 /**
173211 * First-class collection to work with transactional event listeners, i.e. {@link ApplicationListener} instances that
174212 * implement {@link TransactionalApplicationListener}.
0 commit comments