diff --git a/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java b/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java index 468545eb7b..eca9ff7b1b 100644 --- a/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java +++ b/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java @@ -151,34 +151,38 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM * @param event the current event to propagate * @since 4.1 */ - @SuppressWarnings({"unchecked", "rawtypes"}) - protected void invokeListener(ApplicationListener listener, ApplicationEvent event) { + protected void invokeListener(ApplicationListener listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { - listener.onApplicationEvent(event); + doInvokeListener(listener, event); } catch (Throwable err) { errorHandler.handleError(err); } } else { - try { - listener.onApplicationEvent(event); - } - catch (ClassCastException ex) { - String msg = ex.getMessage(); - if (msg == null || msg.startsWith(event.getClass().getName())) { - // Possibly a lambda-defined listener which we could not resolve the generic event type for - Log logger = LogFactory.getLog(getClass()); - if (logger.isDebugEnabled()) { - logger.debug("Non-matching event type for listener: " + listener, ex); - } - } - else { - throw ex; + doInvokeListener(listener, event); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { + try { + listener.onApplicationEvent(event); + } + catch (ClassCastException ex) { + String msg = ex.getMessage(); + if (msg == null || msg.startsWith(event.getClass().getName())) { + // Possibly a lambda-defined listener which we could not resolve the generic event type for + Log logger = LogFactory.getLog(getClass()); + if (logger.isDebugEnabled()) { + logger.debug("Non-matching event type for listener: " + listener, ex); } } + else { + throw ex; + } } } 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 7bf60e7ac9..e1c778ad8c 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 @@ -46,6 +46,7 @@ import org.springframework.core.ResolvableType; import org.springframework.core.annotation.Order; import org.springframework.scheduling.support.TaskUtils; import org.springframework.tests.sample.beans.TestBean; +import org.springframework.util.ReflectionUtils; import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; @@ -447,6 +448,30 @@ public class ApplicationContextEventTests extends AbstractApplicationEventListen context.close(); } + @Test + public void lambdaAsListenerWithErrorHandler() { + final Set seenEvents = new HashSet<>(); + StaticApplicationContext context = new StaticApplicationContext(); + SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster(); + multicaster.setErrorHandler(ReflectionUtils::rethrowRuntimeException); + context.getBeanFactory().registerSingleton( + StaticApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME, multicaster); + ApplicationListener listener = seenEvents::add; + context.addApplicationListener(listener); + context.refresh(); + + MyEvent event1 = new MyEvent(context); + context.publishEvent(event1); + context.publishEvent(new MyOtherEvent(context)); + MyEvent event2 = new MyEvent(context); + context.publishEvent(event2); + assertSame(2, seenEvents.size()); + assertTrue(seenEvents.contains(event1)); + assertTrue(seenEvents.contains(event2)); + + context.close(); + } + @Test public void beanPostProcessorPublishesEvents() { GenericApplicationContext context = new GenericApplicationContext();