@ -67,10 +67,38 @@ public abstract class AbstractApplicationEventMulticaster
@@ -67,10 +67,38 @@ public abstract class AbstractApplicationEventMulticaster
private BeanFactory beanFactory ;
private Object retrievalMutex = this . defaultRetriever ;
@Override
public void setBeanClassLoader ( ClassLoader classLoader ) {
this . beanClassLoader = classLoader ;
}
@Override
public void setBeanFactory ( BeanFactory beanFactory ) {
this . beanFactory = beanFactory ;
if ( beanFactory instanceof ConfigurableBeanFactory ) {
ConfigurableBeanFactory cbf = ( ConfigurableBeanFactory ) beanFactory ;
if ( this . beanClassLoader = = null ) {
this . beanClassLoader = cbf . getBeanClassLoader ( ) ;
}
this . retrievalMutex = cbf . getSingletonMutex ( ) ;
}
}
private BeanFactory getBeanFactory ( ) {
if ( this . beanFactory = = null ) {
throw new IllegalStateException ( "ApplicationEventMulticaster cannot retrieve listener beans " +
"because it is not associated with a BeanFactory" ) ;
}
return this . beanFactory ;
}
@Override
public void addApplicationListener ( ApplicationListener < ? > listener ) {
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
this . defaultRetriever . applicationListeners . add ( listener ) ;
this . retrieverCache . clear ( ) ;
}
@ -78,7 +106,7 @@ public abstract class AbstractApplicationEventMulticaster
@@ -78,7 +106,7 @@ public abstract class AbstractApplicationEventMulticaster
@Override
public void addApplicationListenerBean ( String listenerBeanName ) {
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
this . defaultRetriever . applicationListenerBeans . add ( listenerBeanName ) ;
this . retrieverCache . clear ( ) ;
}
@ -86,7 +114,7 @@ public abstract class AbstractApplicationEventMulticaster
@@ -86,7 +114,7 @@ public abstract class AbstractApplicationEventMulticaster
@Override
public void removeApplicationListener ( ApplicationListener < ? > listener ) {
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
this . defaultRetriever . applicationListeners . remove ( listener ) ;
this . retrieverCache . clear ( ) ;
}
@ -94,7 +122,7 @@ public abstract class AbstractApplicationEventMulticaster
@@ -94,7 +122,7 @@ public abstract class AbstractApplicationEventMulticaster
@Override
public void removeApplicationListenerBean ( String listenerBeanName ) {
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
this . defaultRetriever . applicationListenerBeans . remove ( listenerBeanName ) ;
this . retrieverCache . clear ( ) ;
}
@ -102,34 +130,13 @@ public abstract class AbstractApplicationEventMulticaster
@@ -102,34 +130,13 @@ public abstract class AbstractApplicationEventMulticaster
@Override
public void removeAllListeners ( ) {
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
this . defaultRetriever . applicationListeners . clear ( ) ;
this . defaultRetriever . applicationListenerBeans . clear ( ) ;
this . retrieverCache . clear ( ) ;
}
}
@Override
public void setBeanClassLoader ( ClassLoader classLoader ) {
this . beanClassLoader = classLoader ;
}
@Override
public void setBeanFactory ( BeanFactory beanFactory ) {
this . beanFactory = beanFactory ;
if ( this . beanClassLoader = = null & & beanFactory instanceof ConfigurableBeanFactory ) {
this . beanClassLoader = ( ( ConfigurableBeanFactory ) beanFactory ) . getBeanClassLoader ( ) ;
}
}
private BeanFactory getBeanFactory ( ) {
if ( this . beanFactory = = null ) {
throw new IllegalStateException ( "ApplicationEventMulticaster cannot retrieve listener beans " +
"because it is not associated with a BeanFactory" ) ;
}
return this . beanFactory ;
}
/ * *
* Return a Collection containing all ApplicationListeners .
@ -137,7 +144,7 @@ public abstract class AbstractApplicationEventMulticaster
@@ -137,7 +144,7 @@ public abstract class AbstractApplicationEventMulticaster
* @see org . springframework . context . ApplicationListener
* /
protected Collection < ApplicationListener < ? > > getApplicationListeners ( ) {
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
return this . defaultRetriever . getApplicationListeners ( ) ;
}
}
@ -168,39 +175,38 @@ public abstract class AbstractApplicationEventMulticaster
@@ -168,39 +175,38 @@ public abstract class AbstractApplicationEventMulticaster
( ClassUtils . isCacheSafe ( event . getClass ( ) , this . beanClassLoader ) & &
( sourceType = = null | | ClassUtils . isCacheSafe ( sourceType , this . beanClassLoader ) ) ) ) {
// Fully synchronized building and caching of a ListenerRetriever
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
retriever = this . retrieverCache . get ( cacheKey ) ;
if ( retriever ! = null ) {
return retriever . getApplicationListeners ( ) ;
}
retriever = new ListenerRetriever ( true ) ;
Collection < ApplicationListener < ? > > listeners =
retrieveApplicationListeners ( event , event Type, sourceType , retriever ) ;
retrieveApplicationListeners ( eventType , sourceType , retriever ) ;
this . retrieverCache . put ( cacheKey , retriever ) ;
return listeners ;
}
}
else {
// No ListenerRetriever caching -> no synchronization necessary
return retrieveApplicationListeners ( event , event Type, sourceType , null ) ;
return retrieveApplicationListeners ( eventType , sourceType , null ) ;
}
}
/ * *
* Actually retrieve the application listeners for the given event and source type .
* @param event the application event
* @param eventType the 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 (
ApplicationEvent event , ResolvableType eventType , Class < ? > sourceType , ListenerRetriever retriever ) {
ResolvableType eventType , Class < ? > sourceType , ListenerRetriever retriever ) {
LinkedList < ApplicationListener < ? > > allListeners = new LinkedList < ApplicationListener < ? > > ( ) ;
Set < ApplicationListener < ? > > listeners ;
Set < String > listenerBeans ;
synchronized ( this . defaultRetriever ) {
synchronized ( this . retrievalMutex ) {
listeners = new LinkedHashSet < ApplicationListener < ? > > ( this . defaultRetriever . applicationListeners ) ;
listenerBeans = new LinkedHashSet < String > ( this . defaultRetriever . applicationListenerBeans ) ;
}
@ -270,9 +276,7 @@ public abstract class AbstractApplicationEventMulticaster
@@ -270,9 +276,7 @@ public abstract class AbstractApplicationEventMulticaster
* @return whether the given listener should be included in the candidates
* for the given event type
* /
protected boolean supportsEvent ( ApplicationListener < ? > listener ,
ResolvableType eventType , Class < ? > sourceType ) {
protected boolean supportsEvent ( ApplicationListener < ? > listener , ResolvableType eventType , Class < ? > sourceType ) {
GenericApplicationListener smartListener = ( listener instanceof GenericApplicationListener ?
( GenericApplicationListener ) listener : new GenericApplicationListenerAdapter ( listener ) ) ;
return ( smartListener . supportsEventType ( eventType ) & & smartListener . supportsSourceType ( sourceType ) ) ;