Polish "Add support for explicit generic type in PayloadApplicationEvent"
See gh-24599
This commit is contained in:
parent
6283456ef2
commit
792b366bda
|
|
@ -39,17 +39,7 @@ public class PayloadApplicationEvent<T> extends ApplicationEvent implements Reso
|
||||||
|
|
||||||
private final T payload;
|
private final T payload;
|
||||||
|
|
||||||
@Nullable
|
private final ResolvableType payloadType;
|
||||||
private 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})
|
|
||||||
*/
|
|
||||||
public PayloadApplicationEvent(Object source, T payload) {
|
|
||||||
this(source, payload, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new PayloadApplicationEvent.
|
* Create a new PayloadApplicationEvent.
|
||||||
|
|
@ -61,15 +51,21 @@ public class PayloadApplicationEvent<T> extends ApplicationEvent implements Reso
|
||||||
super(source);
|
super(source);
|
||||||
Assert.notNull(payload, "Payload must not be null");
|
Assert.notNull(payload, "Payload must not be null");
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
this.payloadType = payloadType;
|
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
|
@Override
|
||||||
public ResolvableType getResolvableType() {
|
public ResolvableType getResolvableType() {
|
||||||
if (this.payloadType == null) {
|
|
||||||
this.payloadType = ResolvableType.forInstance(getPayload());
|
|
||||||
}
|
|
||||||
return ResolvableType.forClassWithGenerics(getClass(), this.payloadType);
|
return ResolvableType.forClassWithGenerics(getClass(), this.payloadType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ import org.springframework.context.event.test.GenericEventPojo;
|
||||||
import org.springframework.context.event.test.Identifiable;
|
import org.springframework.context.event.test.Identifiable;
|
||||||
import org.springframework.context.event.test.TestEvent;
|
import org.springframework.context.event.test.TestEvent;
|
||||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
import org.springframework.core.ResolvableType;
|
|
||||||
import org.springframework.core.annotation.AliasFor;
|
import org.springframework.core.annotation.AliasFor;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
@ -623,17 +622,6 @@ class AnnotationDrivenEventListenerTests {
|
||||||
this.eventCollector.assertNoEventReceived(listener);
|
this.eventCollector.assertNoEventReceived(listener);
|
||||||
this.eventCollector.assertTotalEventsCount(0);
|
this.eventCollector.assertTotalEventsCount(0);
|
||||||
}
|
}
|
||||||
@Test
|
|
||||||
public void publishEventWithGeneric() throws NoSuchMethodException {
|
|
||||||
MyAnnotationConfigApplicationContext ctx = new MyAnnotationConfigApplicationContext();
|
|
||||||
context = ctx;
|
|
||||||
ctx.register(MyEventWithGenericListener.class);
|
|
||||||
ctx.refresh();
|
|
||||||
ResolvableType resolvableType = ResolvableType.forMethodParameter(MyEventWithGenericListener.class.getMethod("onMyEventWithGeneric",MyEventWithGeneric.class),0);
|
|
||||||
ctx.publishEvent(new MyEventWithGeneric<String>(),resolvableType);
|
|
||||||
assertThat(MyEventWithGenericListener.count).isEqualTo(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void orderedListeners() {
|
void orderedListeners() {
|
||||||
|
|
@ -1146,29 +1134,4 @@ class AnnotationDrivenEventListenerTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MyAnnotationConfigApplicationContext extends AnnotationConfigApplicationContext{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void publishEvent(Object event, ResolvableType eventType) {
|
|
||||||
super.publishEvent(event, eventType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MyEventWithGeneric<T> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public static class MyEventWithGenericListener{
|
|
||||||
|
|
||||||
public static int count ;
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
public void onMyEventWithGeneric(MyEventWithGeneric<String> event){
|
|
||||||
count ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.PayloadApplicationEvent;
|
import org.springframework.context.PayloadApplicationEvent;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.support.GenericApplicationContext;
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
@ -34,10 +35,40 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
/**
|
/**
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
*/
|
*/
|
||||||
public class PayloadApplicationEventTests {
|
class PayloadApplicationEventTests {
|
||||||
|
|
||||||
@Test
|
@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);
|
ApplicationContext ac = new AnnotationConfigApplicationContext(AuditableListener.class);
|
||||||
|
|
||||||
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
|
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
|
||||||
|
|
@ -46,7 +77,7 @@ public class PayloadApplicationEventTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProgrammaticEventListener() {
|
void testProgrammaticEventListener() {
|
||||||
List<Auditable> events = new ArrayList<>();
|
List<Auditable> events = new ArrayList<>();
|
||||||
ApplicationListener<AuditablePayloadEvent<String>> listener = events::add;
|
ApplicationListener<AuditablePayloadEvent<String>> listener = events::add;
|
||||||
ApplicationListener<AuditablePayloadEvent<Integer>> mismatch = (event -> event.getPayload().intValue());
|
ApplicationListener<AuditablePayloadEvent<Integer>> mismatch = (event -> event.getPayload().intValue());
|
||||||
|
|
@ -62,7 +93,7 @@ public class PayloadApplicationEventTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProgrammaticPayloadListener() {
|
void testProgrammaticPayloadListener() {
|
||||||
List<String> events = new ArrayList<>();
|
List<String> events = new ArrayList<>();
|
||||||
ApplicationListener<PayloadApplicationEvent<String>> listener = ApplicationListener.forPayload(events::add);
|
ApplicationListener<PayloadApplicationEvent<String>> listener = ApplicationListener.forPayload(events::add);
|
||||||
ApplicationListener<PayloadApplicationEvent<Integer>> mismatch = ApplicationListener.forPayload(payload -> payload.intValue());
|
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