|
|
|
@ -145,12 +145,44 @@ public abstract class AbstractApplicationEventMulticaster |
|
|
|
Object source = event.getSource(); |
|
|
|
Object source = event.getSource(); |
|
|
|
Class<?> sourceType = (source != null ? source.getClass() : null); |
|
|
|
Class<?> sourceType = (source != null ? source.getClass() : null); |
|
|
|
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); |
|
|
|
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Quick check for existing entry on ConcurrentHashMap...
|
|
|
|
ListenerRetriever retriever = this.retrieverCache.get(cacheKey); |
|
|
|
ListenerRetriever retriever = this.retrieverCache.get(cacheKey); |
|
|
|
if (retriever != null) { |
|
|
|
if (retriever != null) { |
|
|
|
return retriever.getApplicationListeners(); |
|
|
|
return retriever.getApplicationListeners(); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
|
|
|
|
|
|
|
|
if (this.beanClassLoader == null || |
|
|
|
|
|
|
|
(ClassUtils.isCacheSafe(eventType, this.beanClassLoader) && |
|
|
|
|
|
|
|
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { |
|
|
|
|
|
|
|
// Fully synchronized building and caching of a ListenerRetriever
|
|
|
|
|
|
|
|
synchronized (this.defaultRetriever) { |
|
|
|
|
|
|
|
retriever = this.retrieverCache.get(cacheKey); |
|
|
|
|
|
|
|
if (retriever != null) { |
|
|
|
|
|
|
|
return retriever.getApplicationListeners(); |
|
|
|
|
|
|
|
} |
|
|
|
retriever = new ListenerRetriever(true); |
|
|
|
retriever = new ListenerRetriever(true); |
|
|
|
|
|
|
|
Collection<ApplicationListener> listeners = retrieveApplicationListeners(eventType, sourceType, retriever); |
|
|
|
|
|
|
|
this.retrieverCache.put(cacheKey, retriever); |
|
|
|
|
|
|
|
return listeners; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
// No ListenerRetriever caching -> no synchronization necessary
|
|
|
|
|
|
|
|
return retrieveApplicationListeners(eventType, sourceType, null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Actually retrieve the application listeners for the given event and source type. |
|
|
|
|
|
|
|
* @param eventType the application event type |
|
|
|
|
|
|
|
* @param sourceType the event source type |
|
|
|
|
|
|
|
* @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes) |
|
|
|
|
|
|
|
* @return the pre-filtered list of application listeners for the given event and source type |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private Collection<ApplicationListener> retrieveApplicationListeners( |
|
|
|
|
|
|
|
Class<? extends ApplicationEvent> eventType, Class<?> sourceType, ListenerRetriever retriever) { |
|
|
|
|
|
|
|
|
|
|
|
LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>(); |
|
|
|
LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>(); |
|
|
|
Set<ApplicationListener> listeners; |
|
|
|
Set<ApplicationListener> listeners; |
|
|
|
Set<String> listenerBeans; |
|
|
|
Set<String> listenerBeans; |
|
|
|
@ -160,7 +192,9 @@ public abstract class AbstractApplicationEventMulticaster |
|
|
|
} |
|
|
|
} |
|
|
|
for (ApplicationListener listener : listeners) { |
|
|
|
for (ApplicationListener listener : listeners) { |
|
|
|
if (supportsEvent(listener, eventType, sourceType)) { |
|
|
|
if (supportsEvent(listener, eventType, sourceType)) { |
|
|
|
|
|
|
|
if (retriever != null) { |
|
|
|
retriever.applicationListeners.add(listener); |
|
|
|
retriever.applicationListeners.add(listener); |
|
|
|
|
|
|
|
} |
|
|
|
allListeners.add(listener); |
|
|
|
allListeners.add(listener); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -169,20 +203,16 @@ public abstract class AbstractApplicationEventMulticaster |
|
|
|
for (String listenerBeanName : listenerBeans) { |
|
|
|
for (String listenerBeanName : listenerBeans) { |
|
|
|
ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class); |
|
|
|
ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class); |
|
|
|
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) { |
|
|
|
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) { |
|
|
|
|
|
|
|
if (retriever != null) { |
|
|
|
retriever.applicationListenerBeans.add(listenerBeanName); |
|
|
|
retriever.applicationListenerBeans.add(listenerBeanName); |
|
|
|
|
|
|
|
} |
|
|
|
allListeners.add(listener); |
|
|
|
allListeners.add(listener); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
OrderComparator.sort(allListeners); |
|
|
|
OrderComparator.sort(allListeners); |
|
|
|
if (this.beanClassLoader == null || |
|
|
|
|
|
|
|
(ClassUtils.isCacheSafe(eventType, this.beanClassLoader) && |
|
|
|
|
|
|
|
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { |
|
|
|
|
|
|
|
this.retrieverCache.put(cacheKey, retriever); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return allListeners; |
|
|
|
return allListeners; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Determine whether the given listener supports the given event. |
|
|
|
* Determine whether the given listener supports the given event. |
|
|
|
|