11/*
2- * Copyright 2002-2014 the original author or authors.
2+ * Copyright 2002-2015 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
3131import org .springframework .context .ApplicationEvent ;
3232import org .springframework .context .ApplicationListener ;
3333import org .springframework .core .OrderComparator ;
34+ import org .springframework .core .ResolvableType ;
3435import org .springframework .util .ClassUtils ;
3536import org .springframework .util .ObjectUtils ;
3637
4950 * Alternative implementations could be more sophisticated in those respects.
5051 *
5152 * @author Juergen Hoeller
53+ * @author Stephane Nicoll
5254 * @since 1.2.3
53- * @see #getApplicationListeners(ApplicationEvent)
55+ * @see #getApplicationListeners(ApplicationEvent, ResolvableType )
5456 * @see SimpleApplicationEventMulticaster
5557 */
5658public abstract class AbstractApplicationEventMulticaster
@@ -145,13 +147,16 @@ protected Collection<ApplicationListener<?>> getApplicationListeners() {
145147 * event type. Non-matching listeners get excluded early.
146148 * @param event the event to be propagated. Allows for excluding
147149 * non-matching listeners early, based on cached matching information.
150+ * @param eventType the event type
148151 * @return a Collection of ApplicationListeners
149152 * @see org.springframework.context.ApplicationListener
150153 */
151- protected Collection <ApplicationListener <?>> getApplicationListeners (ApplicationEvent event ) {
154+ protected Collection <ApplicationListener <?>> getApplicationListeners (
155+ ApplicationEvent event , ResolvableType eventType ) {
156+
152157 Object source = event .getSource ();
153158 Class <?> sourceType = (source != null ? source .getClass () : null );
154- ListenerCacheKey cacheKey = new ListenerCacheKey (event . getClass () , sourceType );
159+ ListenerCacheKey cacheKey = new ListenerCacheKey (eventType , sourceType );
155160
156161 // Quick check for existing entry on ConcurrentHashMap...
157162 ListenerRetriever retriever = this .retrieverCache .get (cacheKey );
@@ -169,26 +174,28 @@ protected Collection<ApplicationListener<?>> getApplicationListeners(Application
169174 return retriever .getApplicationListeners ();
170175 }
171176 retriever = new ListenerRetriever (true );
172- Collection <ApplicationListener <?>> listeners = retrieveApplicationListeners (event , sourceType , retriever );
177+ Collection <ApplicationListener <?>> listeners =
178+ retrieveApplicationListeners (event , eventType , sourceType , retriever );
173179 this .retrieverCache .put (cacheKey , retriever );
174180 return listeners ;
175181 }
176182 }
177183 else {
178184 // No ListenerRetriever caching -> no synchronization necessary
179- return retrieveApplicationListeners (event , sourceType , null );
185+ return retrieveApplicationListeners (event , eventType , sourceType , null );
180186 }
181187 }
182188
183189 /**
184190 * Actually retrieve the application listeners for the given event and source type.
185191 * @param event the application event
192+ * @param eventType the event type
186193 * @param sourceType the event source type
187194 * @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
188195 * @return the pre-filtered list of application listeners for the given event and source type
189196 */
190197 private Collection <ApplicationListener <?>> retrieveApplicationListeners (
191- ApplicationEvent event , Class <?> sourceType , ListenerRetriever retriever ) {
198+ ApplicationEvent event , ResolvableType eventType , Class <?> sourceType , ListenerRetriever retriever ) {
192199
193200 LinkedList <ApplicationListener <?>> allListeners = new LinkedList <ApplicationListener <?>>();
194201 Set <ApplicationListener <?>> listeners ;
@@ -198,7 +205,7 @@ private Collection<ApplicationListener<?>> retrieveApplicationListeners(
198205 listenerBeans = new LinkedHashSet <String >(this .defaultRetriever .applicationListenerBeans );
199206 }
200207 for (ApplicationListener <?> listener : listeners ) {
201- if (supportsEvent (listener , event . getClass () , sourceType )) {
208+ if (supportsEvent (listener , eventType , sourceType )) {
202209 if (retriever != null ) {
203210 retriever .applicationListeners .add (listener );
204211 }
@@ -210,10 +217,10 @@ private Collection<ApplicationListener<?>> retrieveApplicationListeners(
210217 for (String listenerBeanName : listenerBeans ) {
211218 try {
212219 Class <?> listenerType = beanFactory .getType (listenerBeanName );
213- if (listenerType == null || supportsEvent (listenerType , event )) {
220+ if (listenerType == null || supportsEvent (listenerType , eventType )) {
214221 ApplicationListener <?> listener =
215222 beanFactory .getBean (listenerBeanName , ApplicationListener .class );
216- if (!allListeners .contains (listener ) && supportsEvent (listener , event . getClass () , sourceType )) {
223+ if (!allListeners .contains (listener ) && supportsEvent (listener , eventType , sourceType )) {
217224 if (retriever != null ) {
218225 retriever .applicationListenerBeans .add (listenerBeanName );
219226 }
@@ -236,37 +243,38 @@ private Collection<ApplicationListener<?>> retrieveApplicationListeners(
236243 * type before trying to instantiate it.
237244 * <p>If this method returns {@code true} for a given listener as a first pass,
238245 * 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.
240247 * @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
242249 * @return whether the given listener should be included in the candidates
243250 * for the given event type
244251 */
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 )) {
247255 return true ;
248256 }
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 ));
251259 }
252260
253261 /**
254262 * Determine whether the given listener supports the given event.
255263 * <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.
259267 * @param listener the target listener to check
260268 * @param eventType the event type to check against
261269 * @param sourceType the source type to check against
262270 * @return whether the given listener should be included in the candidates
263271 * for the given event type
264272 */
265273 protected boolean supportsEvent (ApplicationListener <?> listener ,
266- Class <? extends ApplicationEvent > eventType , Class <?> sourceType ) {
274+ ResolvableType eventType , Class <?> sourceType ) {
267275
268- SmartApplicationListener smartListener = (listener instanceof SmartApplicationListener ?
269- (SmartApplicationListener ) listener : new GenericApplicationListenerAdapter (listener ));
276+ GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
277+ (GenericApplicationListener ) listener : new GenericApplicationListenerAdapter (listener ));
270278 return (smartListener .supportsEventType (eventType ) && smartListener .supportsSourceType (sourceType ));
271279 }
272280
@@ -276,11 +284,11 @@ protected boolean supportsEvent(ApplicationListener<?> listener,
276284 */
277285 private static class ListenerCacheKey {
278286
279- private final Class <?> eventType ;
287+ private final ResolvableType eventType ;
280288
281289 private final Class <?> sourceType ;
282290
283- public ListenerCacheKey (Class <?> eventType , Class <?> sourceType ) {
291+ public ListenerCacheKey (ResolvableType eventType , Class <?> sourceType ) {
284292 this .eventType = eventType ;
285293 this .sourceType = sourceType ;
286294 }
0 commit comments