Introduce TransactionalApplicationListener interface (with callback support)

Includes forPayload methods and common adapter classes for programmatic usage.
Aligns default order values for event handling delegates to LOWEST_PRECEDENCE.

Closes gh-24163
This commit is contained in:
Juergen Hoeller
2020-10-22 15:19:32 +02:00
parent cfc3522641
commit 95110d8257
19 changed files with 905 additions and 184 deletions

View File

@@ -26,6 +26,7 @@ import org.springframework.aop.framework.ProxyFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.PayloadApplicationEvent;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;
import org.springframework.core.annotation.Order;
@@ -161,7 +162,7 @@ public class ApplicationListenerMethodAdapterTests extends AbstractApplicationEv
Method method = ReflectionUtils.findMethod(
SampleEvents.class, "handleGenericString", GenericTestEvent.class);
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
assertThat(adapter.getOrder()).isEqualTo(0);
assertThat(adapter.getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE);
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -22,8 +22,11 @@ import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
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.stereotype.Component;
import static org.assertj.core.api.Assertions.assertThat;
@@ -34,14 +37,42 @@ import static org.assertj.core.api.Assertions.assertThat;
public class PayloadApplicationEventTests {
@Test
@SuppressWarnings({ "rawtypes", "resource" })
public void testEventClassWithInterface() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AuditableListener.class);
AuditablePayloadEvent event = new AuditablePayloadEvent<>(this, "xyz");
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
ac.publishEvent(event);
assertThat(ac.getBean(AuditableListener.class).events.contains(event)).isTrue();
}
@Test
public void testProgrammaticEventListener() {
List<Auditable> events = new ArrayList<>();
ApplicationListener<AuditablePayloadEvent<String>> listener = events::add;
ConfigurableApplicationContext ac = new GenericApplicationContext();
ac.addApplicationListener(listener);
ac.refresh();
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
ac.publishEvent(event);
assertThat(events.contains(event)).isTrue();
}
@Test
public void testProgrammaticPayloadListener() {
List<String> events = new ArrayList<>();
ApplicationListener<PayloadApplicationEvent<String>> listener = ApplicationListener.forPayload(events::add);
ConfigurableApplicationContext ac = new GenericApplicationContext();
ac.addApplicationListener(listener);
ac.refresh();
AuditablePayloadEvent<String> event = new AuditablePayloadEvent<>(this, "xyz");
ac.publishEvent(event);
assertThat(events.contains(event.getPayload())).isTrue();
}
public interface Auditable {
}