Browse Source

Avoid duplicate application listeners (proxy vs. proxy target)

In AbstractApplicationEventMulticaster.retrieveApplicationListeners,
despite best efforts to avoid it, unwrapped proxies (singleton targets)
can end up in the list of programmatically registered listeners. In
order to avoid duplicates, we need to find and replace them by their
proxy counterparts, because if both a proxy and its target end up in
'allListeners', listeners will fire twice.

Fixes #28283.
pull/31407/head
Alexander Kriegisch 2 years ago committed by Juergen Hoeller
parent
commit
20c688e68d
  1. 18
      spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java

18
spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java

@ -263,6 +263,24 @@ public abstract class AbstractApplicationEventMulticaster @@ -263,6 +263,24 @@ public abstract class AbstractApplicationEventMulticaster
if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
// Despite best efforts to avoid it, unwrapped proxies (singleton targets) can end up in the
// list of programmatically registered listeners. In order to avoid duplicates, we need to find
// and replace them by their proxy counterparts, because if both a proxy and its target end up
// in 'allListeners', listeners will fire twice.
ApplicationListener<?> unwrappedListener =
(ApplicationListener<?>) AopProxyUtils.getSingletonTarget(listener);
if (listener != unwrappedListener) {
if (filteredListeners != null && filteredListeners.contains(unwrappedListener)) {
filteredListeners.remove(unwrappedListener);
filteredListeners.add(listener);
}
if (allListeners.contains(unwrappedListener)) {
allListeners.remove(unwrappedListener);
allListeners.add(listener);
}
}
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
if (beanFactory.isSingleton(listenerBeanName)) {

Loading…
Cancel
Save