# Spring 应用事件支持
# Spring ApplicationEvent
支持
Spring 集成提供了对入站和出站ApplicationEvents
的支持,如底层 Spring 框架所定义的那样。有关 Spring 对事件和侦听器的支持的更多信息,请参见Spring Reference Manual (opens new window)。
你需要在项目中包含此依赖项:
Maven
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-event</artifactId>
<version>5.5.9</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-event:5.5.9"
# 接收 Spring 应用事件
要接收事件并将其发送到通道,你可以定义 Spring Integration 的ApplicationEventListeningMessageProducer
实例。这个类是 Spring 的ApplicationListener
接口的实现。默认情况下,它将所有接收到的事件作为 Spring 集成消息传递。要根据事件的类型进行限制,可以使用“eventTypes”属性来配置要接收的事件类型列表。如果接收到的事件有一个Message
实例作为其“源”,则该Message
将按原样传递。否则,如果提供了基于 SPEL 的payloadExpression
,则根据ApplicationEvent
实例对其进行求值。如果事件的源不是Message
实例,并且没有提供payloadExpression
,则ApplicationEvent
本身将作为有效负载传递。
从版本 4.2 开始,ApplicationEventListeningMessageProducer
实现了GenericApplicationListener
,并且可以被配置为不仅接受ApplicationEvent
类型,还接受用于处理有效负载事件的任何类型(自 Spring Framework4.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"/>
在前面的示例中,与“event-types”(可选)属性指定的类型之一相匹配的所有应用程序上下文事件都作为 Spring 集成消息传递到名为“EventChannel”的消息通道。如果下游组件抛出异常,则将包含失败消息和异常的MessagingException
发送到名为“EvenTerrorChannel”的通道。如果指定了 noerror-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 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 IntegrationFlows.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel))
.handle(...)
...
.get();
}
# 发送 Spring 应用程序事件
要发送 Spring ApplicationEvents
,请创建ApplicationEventPublishingMessageHandler
的一个实例,并将其注册到一个端点中。MessageHandler
接口的此实现还实现了 Spring 的ApplicationEventPublisherAware
接口,因此充当 Spring 集成消息和ApplicationEvents
之间的桥梁。
为了方便起见,提供了名称空间支持,以配置带有outbound-channel-adapter
元素的ApplicationEventPublishingMessageHandler
元素,如下例所示:
<int:channel id="eventChannel"/>
<int-event:outbound-channel-adapter channel="eventChannel"/>
如果使用PollableChannel
(例如QueueChannel
),还可以提供poller
元素的子元素。你还可以为该 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"/>
在前面的示例中,发送到“EventChannel”通道的所有消息都作为ApplicationEvent
实例发布到在相同的 Spring ApplicationListener
中注册的任何相关ApplicationContext
实例。如果消息的有效负载是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 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);
}