diff --git a/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java b/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java index 7b0d6cd6c25..02b4a36642b 100644 --- a/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java +++ b/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java @@ -24,6 +24,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -98,7 +100,8 @@ class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, try { ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster(); multicaster.removeApplicationListener(applicationListener); - multicaster.removeApplicationListenerBean(beanName); + multicaster.removeApplicationListenerBean( + bean instanceof FactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName); } catch (IllegalStateException ex) { // ApplicationEventMulticaster not initialized yet - no need to remove a listener diff --git a/spring-context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java b/spring-context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java index 1f2f22efe80..1b5b62b6033 100644 --- a/spring-context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java +++ b/spring-context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java @@ -30,6 +30,7 @@ import org.mockito.ArgumentCaptor; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanPostProcessor; @@ -435,12 +436,15 @@ class ApplicationContextEventTests extends AbstractApplicationEventListenerTests RootBeanDefinition listener1Def = new RootBeanDefinition(MyOrderedListener1.class); listener1Def.setDependsOn("nestedChild"); context.registerBeanDefinition("listener1", listener1Def); + context.registerBeanDefinition("listenerFb", new RootBeanDefinition(MyFactoryBeanListener.class)); context.refresh(); MyOrderedListener1 listener1 = context.getBean("listener1", MyOrderedListener1.class); + MyFactoryBeanListener listenerFb = context.getBean("&listenerFb", MyFactoryBeanListener.class); MyEvent event1 = new MyEvent(context); context.publishEvent(event1); assertThat(listener1.seenEvents).contains(event1); + assertThat(listenerFb.seenEvents).contains(event1); SimpleApplicationEventMulticaster multicaster = context.getBean(SimpleApplicationEventMulticaster.class); assertThat(multicaster.getApplicationListeners()).isNotEmpty(); @@ -782,6 +786,27 @@ class ApplicationContextEventTests extends AbstractApplicationEventListenerTests } + public static class MyFactoryBeanListener implements FactoryBean, ApplicationListener { + + public final List seenEvents = new ArrayList<>(); + + @Override + public void onApplicationEvent(ApplicationEvent event) { + this.seenEvents.add(event); + } + + @Override + public String getObject() { + return ""; + } + + @Override + public Class getObjectType() { + return String.class; + } + } + + public static class EventPublishingBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware { private ApplicationContext applicationContext;