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");