1
1
/*
2
- * Copyright 2002-2014 the original author or authors.
2
+ * Copyright 2002-2015 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
31
31
import org .springframework .context .ApplicationEvent ;
32
32
import org .springframework .context .ApplicationListener ;
33
33
import org .springframework .core .OrderComparator ;
34
+ import org .springframework .core .ResolvableType ;
34
35
import org .springframework .util .ClassUtils ;
35
36
import org .springframework .util .ObjectUtils ;
36
37
49
50
* Alternative implementations could be more sophisticated in those respects.
50
51
*
51
52
* @author Juergen Hoeller
53
+ * @author Stephane Nicoll
52
54
* @since 1.2.3
53
- * @see #getApplicationListeners(ApplicationEvent)
55
+ * @see #getApplicationListeners(ApplicationEvent, ResolvableType )
54
56
* @see SimpleApplicationEventMulticaster
55
57
*/
56
58
public abstract class AbstractApplicationEventMulticaster
@@ -145,13 +147,16 @@ protected Collection<ApplicationListener<?>> getApplicationListeners() {
145
147
* event type. Non-matching listeners get excluded early.
146
148
* @param event the event to be propagated. Allows for excluding
147
149
* non-matching listeners early, based on cached matching information.
150
+ * @param eventType the event type
148
151
* @return a Collection of ApplicationListeners
149
152
* @see org.springframework.context.ApplicationListener
150
153
*/
151
- protected Collection <ApplicationListener <?>> getApplicationListeners (ApplicationEvent event ) {
154
+ protected Collection <ApplicationListener <?>> getApplicationListeners (
155
+ ApplicationEvent event , ResolvableType eventType ) {
156
+
152
157
Object source = event .getSource ();
153
158
Class <?> sourceType = (source != null ? source .getClass () : null );
154
- ListenerCacheKey cacheKey = new ListenerCacheKey (event . getClass () , sourceType );
159
+ ListenerCacheKey cacheKey = new ListenerCacheKey (eventType , sourceType );
155
160
156
161
// Quick check for existing entry on ConcurrentHashMap...
157
162
ListenerRetriever retriever = this .retrieverCache .get (cacheKey );
@@ -169,26 +174,28 @@ protected Collection<ApplicationListener<?>> getApplicationListeners(Application
169
174
return retriever .getApplicationListeners ();
170
175
}
171
176
retriever = new ListenerRetriever (true );
172
- Collection <ApplicationListener <?>> listeners = retrieveApplicationListeners (event , sourceType , retriever );
177
+ Collection <ApplicationListener <?>> listeners =
178
+ retrieveApplicationListeners (event , eventType , sourceType , retriever );
173
179
this .retrieverCache .put (cacheKey , retriever );
174
180
return listeners ;
175
181
}
176
182
}
177
183
else {
178
184
// No ListenerRetriever caching -> no synchronization necessary
179
- return retrieveApplicationListeners (event , sourceType , null );
185
+ return retrieveApplicationListeners (event , eventType , sourceType , null );
180
186
}
181
187
}
182
188
183
189
/**
184
190
* Actually retrieve the application listeners for the given event and source type.
185
191
* @param event the application event
192
+ * @param eventType the event type
186
193
* @param sourceType the event source type
187
194
* @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
188
195
* @return the pre-filtered list of application listeners for the given event and source type
189
196
*/
190
197
private Collection <ApplicationListener <?>> retrieveApplicationListeners (
191
- ApplicationEvent event , Class <?> sourceType , ListenerRetriever retriever ) {
198
+ ApplicationEvent event , ResolvableType eventType , Class <?> sourceType , ListenerRetriever retriever ) {
192
199
193
200
LinkedList <ApplicationListener <?>> allListeners = new LinkedList <ApplicationListener <?>>();
194
201
Set <ApplicationListener <?>> listeners ;
@@ -198,7 +205,7 @@ private Collection<ApplicationListener<?>> retrieveApplicationListeners(
198
205
listenerBeans = new LinkedHashSet <String >(this .defaultRetriever .applicationListenerBeans );
199
206
}
200
207
for (ApplicationListener <?> listener : listeners ) {
201
- if (supportsEvent (listener , event . getClass () , sourceType )) {
208
+ if (supportsEvent (listener , eventType , sourceType )) {
202
209
if (retriever != null ) {
203
210
retriever .applicationListeners .add (listener );
204
211
}
@@ -210,10 +217,10 @@ private Collection<ApplicationListener<?>> retrieveApplicationListeners(
210
217
for (String listenerBeanName : listenerBeans ) {
211
218
try {
212
219
Class <?> listenerType = beanFactory .getType (listenerBeanName );
213
- if (listenerType == null || supportsEvent (listenerType , event )) {
220
+ if (listenerType == null || supportsEvent (listenerType , eventType )) {
214
221
ApplicationListener <?> listener =
215
222
beanFactory .getBean (listenerBeanName , ApplicationListener .class );
216
- if (!allListeners .contains (listener ) && supportsEvent (listener , event . getClass () , sourceType )) {
223
+ if (!allListeners .contains (listener ) && supportsEvent (listener , eventType , sourceType )) {
217
224
if (retriever != null ) {
218
225
retriever .applicationListenerBeans .add (listenerBeanName );
219
226
}
@@ -236,37 +243,38 @@ private Collection<ApplicationListener<?>> retrieveApplicationListeners(
236
243
* type before trying to instantiate it.
237
244
* <p>If this method returns {@code true} for a given listener as a first pass,
238
245
* the listener instance will get retrieved and fully evaluated through a
239
- * {@link #supportsEvent(ApplicationListener, Class , Class)} call afterwards.
246
+ * {@link #supportsEvent(ApplicationListener,ResolvableType , Class)} call afterwards.
240
247
* @param listenerType the listener's type as determined by the BeanFactory
241
- * @param event the event to check
248
+ * @param eventType the event type to check
242
249
* @return whether the given listener should be included in the candidates
243
250
* for the given event type
244
251
*/
245
- protected boolean supportsEvent (Class <?> listenerType , ApplicationEvent event ) {
246
- if (SmartApplicationListener .class .isAssignableFrom (listenerType )) {
252
+ protected boolean supportsEvent (Class <?> listenerType , ResolvableType eventType ) {
253
+ if (GenericApplicationListener .class .isAssignableFrom (listenerType )
254
+ || SmartApplicationListener .class .isAssignableFrom (listenerType )) {
247
255
return true ;
248
256
}
249
- Class <?> declaredEventType = GenericApplicationListenerAdapter .resolveDeclaredEventType (listenerType );
250
- return (declaredEventType == null || declaredEventType .isInstance ( event ));
257
+ ResolvableType declaredEventType = GenericApplicationListenerAdapter .resolveDeclaredEventType (listenerType );
258
+ return (declaredEventType == null || declaredEventType .isAssignableFrom ( eventType ));
251
259
}
252
260
253
261
/**
254
262
* Determine whether the given listener supports the given event.
255
263
* <p>The default implementation detects the {@link SmartApplicationListener}
256
- * interface . In case of a standard {@link ApplicationListener}, a
257
- * {@link GenericApplicationListenerAdapter} will be used to introspect
258
- * the generically declared type of the target listener.
264
+ * and {@link GenericApplicationListener} interfaces . In case of a standard
265
+ * {@link ApplicationListener}, a {@link GenericApplicationListenerAdapter}
266
+ * will be used to introspect the generically declared type of the target listener.
259
267
* @param listener the target listener to check
260
268
* @param eventType the event type to check against
261
269
* @param sourceType the source type to check against
262
270
* @return whether the given listener should be included in the candidates
263
271
* for the given event type
264
272
*/
265
273
protected boolean supportsEvent (ApplicationListener <?> listener ,
266
- Class <? extends ApplicationEvent > eventType , Class <?> sourceType ) {
274
+ ResolvableType eventType , Class <?> sourceType ) {
267
275
268
- SmartApplicationListener smartListener = (listener instanceof SmartApplicationListener ?
269
- (SmartApplicationListener ) listener : new GenericApplicationListenerAdapter (listener ));
276
+ GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
277
+ (GenericApplicationListener ) listener : new GenericApplicationListenerAdapter (listener ));
270
278
return (smartListener .supportsEventType (eventType ) && smartListener .supportsSourceType (sourceType ));
271
279
}
272
280
@@ -276,11 +284,11 @@ protected boolean supportsEvent(ApplicationListener<?> listener,
276
284
*/
277
285
private static class ListenerCacheKey {
278
286
279
- private final Class <?> eventType ;
287
+ private final ResolvableType eventType ;
280
288
281
289
private final Class <?> sourceType ;
282
290
283
- public ListenerCacheKey (Class <?> eventType , Class <?> sourceType ) {
291
+ public ListenerCacheKey (ResolvableType eventType , Class <?> sourceType ) {
284
292
this .eventType = eventType ;
285
293
this .sourceType = sourceType ;
286
294
}
0 commit comments