Leniently handle lambda-defined listeners with ErrorHandler as well

Issue: SPR-15838
(cherry picked from commit dd2bbcb)
This commit is contained in:
Juergen Hoeller 2017-08-01 12:06:41 +02:00
parent 0088922dfd
commit f948742781
2 changed files with 46 additions and 17 deletions

View File

@ -151,18 +151,23 @@ 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 {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
@ -180,6 +185,5 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
}
}
}
}
}

View File

@ -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<MyEvent> 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<MyEvent> 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();