15
15
*/
16
16
package org .springframework .modulith .events .support ;
17
17
18
+ import java .lang .reflect .Method ;
18
19
import java .util .Collection ;
19
20
import java .util .List ;
20
21
import java .util .function .Consumer ;
29
30
import org .springframework .context .PayloadApplicationEvent ;
30
31
import org .springframework .context .event .AbstractApplicationEventMulticaster ;
31
32
import org .springframework .context .event .ApplicationEventMulticaster ;
33
+ import org .springframework .context .event .ApplicationListenerMethodAdapter ;
32
34
import org .springframework .core .ResolvableType ;
33
35
import org .springframework .core .annotation .AnnotationAwareOrderComparator ;
34
36
import org .springframework .core .env .Environment ;
35
37
import org .springframework .lang .NonNull ;
38
+ import org .springframework .lang .Nullable ;
36
39
import org .springframework .modulith .events .core .EventPublication ;
37
40
import org .springframework .modulith .events .core .EventPublicationRegistry ;
38
41
import org .springframework .modulith .events .core .PublicationTargetIdentifier ;
39
42
import org .springframework .transaction .event .TransactionPhase ;
40
43
import org .springframework .transaction .event .TransactionalApplicationListener ;
41
44
import org .springframework .transaction .event .TransactionalEventListener ;
42
45
import org .springframework .util .Assert ;
46
+ import org .springframework .util .ReflectionUtils ;
43
47
44
48
/**
45
49
* An {@link ApplicationEventMulticaster} to register {@link EventPublication}s in an {@link EventPublicationRegistry}
@@ -56,11 +60,17 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
56
60
implements SmartInitializingSingleton {
57
61
58
62
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 );
59
65
static final String REPUBLISH_ON_RESTART = "spring.modulith.republish-outstanding-events-on-restart" ;
60
66
61
67
private final @ NonNull Supplier <EventPublicationRegistry > registry ;
62
68
private final @ NonNull Supplier <Environment > environment ;
63
69
70
+ static {
71
+ ReflectionUtils .makeAccessible (SUPPORTS_METHOD );
72
+ }
73
+
64
74
/**
65
75
* Creates a new {@link PersistentApplicationEventMulticaster} for the given {@link EventPublicationRegistry}.
66
76
*
@@ -92,7 +102,7 @@ public void multicastEvent(ApplicationEvent event) {
92
102
*/
93
103
@ Override
94
104
@ SuppressWarnings ({ "unchecked" , "rawtypes" })
95
- public void multicastEvent (ApplicationEvent event , ResolvableType eventType ) {
105
+ public void multicastEvent (ApplicationEvent event , @ Nullable ResolvableType eventType ) {
96
106
97
107
var type = eventType == null ? ResolvableType .forInstance (event ) : eventType ;
98
108
var listeners = getApplicationListeners (event , type );
@@ -109,6 +119,22 @@ public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
109
119
}
110
120
}
111
121
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
+
112
138
/*
113
139
* (non-Javadoc)
114
140
* @see org.springframework.beans.factory.SmartInitializingSingleton#afterSingletonsInstantiated()
@@ -169,6 +195,18 @@ private static Object getEventToPersist(ApplicationEvent event) {
169
195
: event ;
170
196
}
171
197
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
+
172
210
/**
173
211
* First-class collection to work with transactional event listeners, i.e. {@link ApplicationListener} instances that
174
212
* implement {@link TransactionalApplicationListener}.
0 commit comments