跳到主要内容

Spring ApplicationEvent 支持

QWen Plus 中英对照 Spring ApplicationEvent Support Spring ApplicationEvent Support

Spring Integration 提供了对传入和传出的 ApplicationEvents 的支持,这些事件由底层的 Spring Framework 定义。有关 Spring 对事件和监听器支持的更多信息,请参阅 Spring 参考手册

你需要将这个依赖添加到你的项目中:

<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-event</artifactId>
<version>6.4.2</version>
</dependency>
xml

接收 Spring 应用事件

要接收事件并将其发送到通道,你可以定义 Spring Integration 的 ApplicationEventListeningMessageProducer 的一个实例。这个类是 Spring 的 ApplicationListener 接口的一个实现。默认情况下,它会将所有接收到的事件作为 Spring Integration 消息传递。为了根据事件类型进行限制,你可以使用 'eventTypes' 属性来配置你想要接收的事件类型列表。如果接收到的事件有一个 Message 实例作为其 'source',那么该 Message 将原样传递。否则,如果提供了一个基于 SpEL 的 payloadExpression,则该表达式将针对 ApplicationEvent 实例进行求值。如果事件的源不是 Message 实例且未提供 payloadExpression,则 ApplicationEvent 本身将作为有效负载传递。

从 4.2 版本开始,ApplicationEventListeningMessageProducer 实现了 GenericApplicationListener,可以配置为不仅接受 ApplicationEvent 类型,还可以接受任何类型来处理有效负载事件(这也是自 Spring Framework 4.2 开始支持的)。当接受的事件是 PayloadApplicationEvent 的实例时,其 payload 将用于要发送的消息。

为了方便起见,提供了命名空间支持,以使用 inbound-channel-adapter 元素配置 ApplicationEventListeningMessageProducer,如下例所示:

<int-event:inbound-channel-adapter channel="eventChannel"
error-channel="eventErrorChannel"
event-types="example.FooEvent, example.BarEvent, java.util.Date"/>

<int:publish-subscribe-channel id="eventChannel"/>
xml

在前面的例子中,所有与 'event-types'(可选)属性指定的类型之一匹配的应用程序上下文事件都会作为 Spring Integration 消息发送到名为 'eventChannel' 的消息通道。如果下游组件抛出异常,则会将包含失败消息和异常的 MessagingException 发送到名为 'eventErrorChannel' 的通道。如果没有指定 error-channel 并且下游通道是同步的,则异常会传播给调用者。

使用 Java 配置相同的适配器:

@Bean
public ApplicationEventListeningMessageProducer eventsAdapter(
MessageChannel eventChannel, MessageChannel eventErrorChannel) {

ApplicationEventListeningMessageProducer producer =
new ApplicationEventListeningMessageProducer();
producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);
producer.setOutputChannel(eventChannel);
producer.setErrorChannel(eventErrorChannel);
return producer;
}
java

使用 Java DSL:

@Bean
public ApplicationEventListeningMessageProducer eventsAdapter() {

ApplicationEventListeningMessageProducer producer =
new ApplicationEventListeningMessageProducer();
producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);
return producer;
}

@Bean
public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer eventsAdapter,
MessageChannel eventErrorChannel) {

return IntegrationFlow.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel))
.handle(...)
...
.get();
}
java

发送 Spring 应用程序事件

要发送 Spring ApplicationEvents,请创建 ApplicationEventPublishingMessageHandler 的实例,并在端点内注册它。这个 MessageHandler 接口的实现还实现了 Spring 的 ApplicationEventPublisherAware 接口,因此充当了 Spring Integration 消息和 ApplicationEvents 之间的桥梁。

为了方便起见,提供了命名空间支持,以使用 outbound-channel-adapter 元素配置 ApplicationEventPublishingMessageHandler,如下例所示:

<int:channel id="eventChannel"/>

<int-event:outbound-channel-adapter channel="eventChannel"/>
xml

如果你使用 PollableChannel(例如 QueueChannel),你也可以提供 outbound-channel-adapter 元素的 poller 子元素。你还可以选择性地为该轮询器提供一个 task-executor 引用。以下示例同时展示了这两点:

<int:channel id="eventChannel">
<int:queue/>
</int:channel>

<int-event:outbound-channel-adapter channel="eventChannel">
<int:poller max-messages-per-poll="1" task-executor="executor" fixed-rate="100"/>
</int-event:outbound-channel-adapter>

<task:executor id="executor" pool-size="5"/>
xml

在前面的例子中,发送到 'eventChannel' 通道的所有消息都会作为 ApplicationEvent 实例发布给在同一 Spring ApplicationContext 中注册的任何相关 ApplicationListener 实例。如果消息的有效负载是 ApplicationEvent,则它将原样传递。否则,消息本身将被包装在一个 MessagingEvent 实例中。

从 4.2 版本开始,您可以使用 publish-payload 布尔属性配置 ApplicationEventPublishingMessageHandler (<int-event:outbound-channel-adapter>),以直接发布应用程序上下文的 payload,而不是将其包装成一个 MessagingEvent 实例。

要使用 Java 配置配置适配器:

@Bean
@ServiceActivator(inputChannel = "eventChannel")
public ApplicationEventPublishingMessageHandler eventHandler() {
ApplicationEventPublishingMessageHandler handler =
new ApplicationEventPublishingMessageHandler();
handler.setPublishPayload(true);
return handler;
}
java

使用 Java DSL:

@Bean
public ApplicationEventPublishingMessageHandler eventHandler() {
ApplicationEventPublishingMessageHandler handler =
new ApplicationEventPublishingMessageHandler();
handler.setPublishPayload(true);
return handler;
}

@Bean
// MessageChannel is "eventsFlow.input"
public IntegrationFlow eventsOutFlow(ApplicationEventPublishingMessageHandler eventHandler) {
return f -> f.handle(eventHandler);
}
java

@Publisher 注解也可以与 @EventListener 结合使用:

@Configuration
@EnableIntegration
@EnablePublisher
public static class ContextConfiguration {

@Bean
QueueChannel eventFromPublisher() {
return new QueueChannel();
}

@EventListener
@Publisher("eventFromPublisher")
public String publishEventToChannel(TestApplicationEvent3 testApplicationEvent3) {
return testApplicationEvent3.getSource().toString();
}

}
java

在这种情况下,事件监听器方法的返回值将作为 Message 的有效负载发布到该 eventFromPublisher 频道。有关 @Publisher 的更多信息,请参阅 注解驱动的配置部分。