diff --git a/spring-context/src/main/java/org/springframework/context/PayloadApplicationEvent.java b/spring-context/src/main/java/org/springframework/context/PayloadApplicationEvent.java index 38633b9c44a..addcbc5dd97 100644 --- a/spring-context/src/main/java/org/springframework/context/PayloadApplicationEvent.java +++ b/spring-context/src/main/java/org/springframework/context/PayloadApplicationEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.context; +import java.util.function.Consumer; + import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableTypeProvider; import org.springframework.util.Assert; @@ -23,11 +25,12 @@ import org.springframework.util.Assert; /** * An {@link ApplicationEvent} that carries an arbitrary payload. * - *

Mainly intended for internal use within the framework. - * * @author Stephane Nicoll + * @author Juergen Hoeller * @since 4.2 * @param the payload type of the event + * @see ApplicationEventPublisher#publishEvent(Object) + * @see ApplicationListener#forPayload(Consumer) */ @SuppressWarnings("serial") public class PayloadApplicationEvent extends ApplicationEvent implements ResolvableTypeProvider { 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 2ca8e8d092d..d1f9b8ca330 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; +import org.springframework.context.PayloadApplicationEvent; import org.springframework.core.ResolvableType; import org.springframework.lang.Nullable; import org.springframework.util.ErrorHandler; @@ -55,6 +56,9 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM @Nullable private ErrorHandler errorHandler; + @Nullable + private volatile Log lazyLogger; + /** * Create a new SimpleApplicationEventMulticaster. @@ -173,12 +177,18 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM } catch (ClassCastException ex) { String msg = ex.getMessage(); - if (msg == null || matchesClassCastMessage(msg, event.getClass())) { + if (msg == null || matchesClassCastMessage(msg, event.getClass()) || + (event instanceof PayloadApplicationEvent && + matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) { // Possibly a lambda-defined listener which we could not resolve the generic event type for - // -> let's suppress the exception and just log a debug message. - Log logger = LogFactory.getLog(getClass()); - if (logger.isTraceEnabled()) { - logger.trace("Non-matching event type for listener: " + listener, ex); + // -> let's suppress the exception. + Log loggerToUse = this.lazyLogger; + if (loggerToUse == null) { + loggerToUse = LogFactory.getLog(getClass()); + this.lazyLogger = loggerToUse; + } + if (loggerToUse.isTraceEnabled()) { + loggerToUse.trace("Non-matching event type for listener: " + listener, ex); } } else { diff --git a/spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java b/spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java index 39db32f0ce0..c752623bb55 100644 --- a/spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java +++ b/spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,9 +49,11 @@ public class PayloadApplicationEventTests { public void testProgrammaticEventListener() { List events = new ArrayList<>(); ApplicationListener> listener = events::add; + ApplicationListener> mismatch = (event -> event.getPayload().intValue()); ConfigurableApplicationContext ac = new GenericApplicationContext(); ac.addApplicationListener(listener); + ac.addApplicationListener(mismatch); ac.refresh(); AuditablePayloadEvent event = new AuditablePayloadEvent<>(this, "xyz"); @@ -63,9 +65,11 @@ public class PayloadApplicationEventTests { public void testProgrammaticPayloadListener() { List events = new ArrayList<>(); ApplicationListener> listener = ApplicationListener.forPayload(events::add); + ApplicationListener> mismatch = ApplicationListener.forPayload(payload -> payload.intValue()); ConfigurableApplicationContext ac = new GenericApplicationContext(); ac.addApplicationListener(listener); + ac.addApplicationListener(mismatch); ac.refresh(); AuditablePayloadEvent event = new AuditablePayloadEvent<>(this, "xyz");