Merge pull request #24599 from chenqimiao
* pr/24599: Polish "Add support for explicit generic type in PayloadApplicationEvent" Add support for explicit generic type in PayloadApplicationEvent Closes gh-24599
This commit is contained in:
commit
5589e6ceed
|
@ -20,6 +20,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.ResolvableTypeProvider;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
@ -27,6 +28,7 @@ import org.springframework.util.Assert;
|
|||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @author Qimiao Chen
|
||||
* @since 4.2
|
||||
* @param <T> the payload type of the event
|
||||
* @see ApplicationEventPublisher#publishEvent(Object)
|
||||
|
@ -37,22 +39,34 @@ public class PayloadApplicationEvent<T> extends ApplicationEvent implements Reso
|
|||
|
||||
private final T payload;
|
||||
|
||||
private final ResolvableType payloadType;
|
||||
|
||||
/**
|
||||
* Create a new PayloadApplicationEvent.
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param payload the payload object (never {@code null})
|
||||
* @param payloadType the type object of payload object (can be {@code null})
|
||||
*/
|
||||
public PayloadApplicationEvent(Object source, T payload) {
|
||||
public PayloadApplicationEvent(Object source, T payload, @Nullable ResolvableType payloadType) {
|
||||
super(source);
|
||||
Assert.notNull(payload, "Payload must not be null");
|
||||
this.payload = payload;
|
||||
this.payloadType = (payloadType != null) ? payloadType : ResolvableType.forInstance(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PayloadApplicationEvent, using the instance to infer its type.
|
||||
* @param source the object on which the event initially occurred (never {@code null})
|
||||
* @param payload the payload object (never {@code null})
|
||||
*/
|
||||
public PayloadApplicationEvent(Object source, T payload) {
|
||||
this(source, payload, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ResolvableType getResolvableType() {
|
||||
return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getPayload()));
|
||||
return ResolvableType.forClassWithGenerics(getClass(), this.payloadType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -407,7 +407,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
|||
applicationEvent = (ApplicationEvent) event;
|
||||
}
|
||||
else {
|
||||
applicationEvent = new PayloadApplicationEvent<>(this, event);
|
||||
applicationEvent = new PayloadApplicationEvent<>(this, event, eventType);
|
||||
if (eventType == null) {
|
||||
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
|||
import org.springframework.context.PayloadApplicationEvent;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -34,10 +35,40 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class PayloadApplicationEventTests {
|
||||
class PayloadApplicationEventTests {
|
||||
|
||||
@Test
|
||||
public void testEventClassWithInterface() {
|
||||
void payloadApplicationEventWithNoTypeUsesInstance() {
|
||||
NumberHolder<Integer> payload = new NumberHolder<>(42);
|
||||
PayloadApplicationEvent<NumberHolder<Integer>> event = new PayloadApplicationEvent<>(this, payload);
|
||||
assertThat(event.getResolvableType()).satisfies(eventType -> {
|
||||
assertThat(eventType.toClass()).isEqualTo(PayloadApplicationEvent.class);
|
||||
assertThat(eventType.getGenerics()).hasSize(1);
|
||||
assertThat(eventType.getGenerics()[0]).satisfies(bodyType -> {
|
||||
assertThat(bodyType.toClass()).isEqualTo(NumberHolder.class);
|
||||
assertThat(bodyType.hasUnresolvableGenerics()).isTrue();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void payloadApplicationEventWithType() {
|
||||
NumberHolder<Integer> payload = new NumberHolder<>(42);
|
||||
ResolvableType payloadType = ResolvableType.forClassWithGenerics(NumberHolder.class, Integer.class);
|
||||
PayloadApplicationEvent<NumberHolder<Integer>> event = new PayloadApplicationEvent<>(this, payload, payloadType);
|
||||
assertThat(event.getResolvableType()).satisfies(eventType -> {
|
||||
assertThat(eventType.toClass()).isEqualTo(PayloadApplicationEvent.class);
|
||||
assertThat(eventType.getGenerics()).hasSize(1);
|
||||
assertThat(eventType.getGenerics()[0]).satisfies(bodyType -> {
|
||||
assertThat(bodyType.toClass()).isEqualTo(NumberHolder.class);
|
||||
assertThat(bodyType.hasUnresolvableGenerics()).isFalse();
|
||||
assertThat(bodyType.getGenerics()[0].toClass()).isEqualTo(Integer.class);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEventClassWithInterface() {
|
||||
ApplicationContext ac = new AnnotationConfigApplicationContext(AuditableListener.class);
|
||||
|
||||
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
|
||||
|
@ -46,7 +77,7 @@ public class PayloadApplicationEventTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testProgrammaticEventListener() {
|
||||
void testProgrammaticEventListener() {
|
||||
List<Auditable> events = new ArrayList<>();
|
||||
ApplicationListener<AuditablePayloadEvent<String>> listener = events::add;
|
||||
ApplicationListener<AuditablePayloadEvent<Integer>> mismatch = (event -> event.getPayload().intValue());
|
||||
|
@ -62,7 +93,7 @@ public class PayloadApplicationEventTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testProgrammaticPayloadListener() {
|
||||
void testProgrammaticPayloadListener() {
|
||||
List<String> events = new ArrayList<>();
|
||||
ApplicationListener<PayloadApplicationEvent<String>> listener = ApplicationListener.forPayload(events::add);
|
||||
ApplicationListener<PayloadApplicationEvent<Integer>> mismatch = ApplicationListener.forPayload(payload -> payload.intValue());
|
||||
|
@ -102,4 +133,14 @@ public class PayloadApplicationEventTests {
|
|||
}
|
||||
}
|
||||
|
||||
static class NumberHolder<T extends Number> {
|
||||
|
||||
private T number;
|
||||
|
||||
public NumberHolder(T number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue