AbstractApplicationContext's ApplicationListenerDetector removes listeners from ApplicationEventMulticaster on individual destruction

Issue: SPR-7856
This commit is contained in:
Juergen Hoeller
2013-10-30 12:30:13 +01:00
parent eddb125836
commit 0fe49629c0
3 changed files with 52 additions and 7 deletions

View File

@@ -341,7 +341,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
* @return the internal ApplicationEventMulticaster (never {@code null})
* @throws IllegalStateException if the context has not been initialized yet
*/
private ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
if (this.applicationEventMulticaster == null) {
throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
"call 'refresh' before multicasting events via the context: " + this);
@@ -354,7 +354,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
* @return the internal LifecycleProcessor (never {@code null})
* @throws IllegalStateException if the context has not been initialized yet
*/
private LifecycleProcessor getLifecycleProcessor() {
LifecycleProcessor getLifecycleProcessor() {
if (this.lifecycleProcessor == null) {
throw new IllegalStateException("LifecycleProcessor not initialized - " +
"call 'refresh' before invoking lifecycle methods via the context: " + this);

View File

@@ -31,12 +31,12 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
@@ -177,7 +177,7 @@ class PostProcessorRegistrationDelegate {
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, ConfigurableApplicationContext applicationContext) {
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
@@ -319,15 +319,15 @@ class PostProcessorRegistrationDelegate {
* BeanPostProcessor that detects beans which implement the ApplicationListener interface.
* This catches beans that can't reliably be detected by getBeanNamesForType.
*/
private static class ApplicationListenerDetector implements MergedBeanDefinitionPostProcessor {
private static class ApplicationListenerDetector implements MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor {
private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);
private final ConfigurableApplicationContext applicationContext;
private final AbstractApplicationContext applicationContext;
private final Map<String, Boolean> singletonNames = new ConcurrentHashMap<String, Boolean>(64);
public ApplicationListenerDetector(ConfigurableApplicationContext applicationContext) {
public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@@ -365,6 +365,14 @@ class PostProcessorRegistrationDelegate {
}
return bean;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
this.applicationContext.getApplicationEventMulticaster().removeApplicationListener((ApplicationListener) bean);
this.applicationContext.getApplicationEventMulticaster().removeApplicationListenerBean(beanName);
}
}
}
}