Spring ApplicationEvent 支援

Spring Integration 提供了對輸入和輸出 ApplicationEvents 的支援,這些事件由底層的 Spring Framework 定義。如需 Spring 對事件和監聽器支援的詳細資訊,請參閱 Spring Reference Manual

您需要將此依賴項包含到您的專案中

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-event</artifactId>
    <version>6.3.5</version>
</dependency>
compile "org.springframework.integration:spring-integration-event:6.3.5"

接收 Spring Application Events

若要接收事件並將其傳送到通道,您可以定義 Spring Integration 的 ApplicationEventListeningMessageProducer 實例。此類別是 Spring ApplicationListener 介面的實作。預設情況下,它會將所有接收到的事件作為 Spring Integration 訊息傳遞。若要根據事件類型進行限制,您可以使用 'eventTypes' 屬性來設定您想要接收的事件類型列表。如果接收到的事件的 'source' 是 Message 實例,則該 Message 會按原樣傳遞。否則,如果已提供基於 SpEL 的 payloadExpression,則會針對 ApplicationEvent 實例評估該表達式。如果事件的來源不是 Message 實例,且未提供 payloadExpression,則 ApplicationEvent 本身會作為 Payload 傳遞。

從 4.2 版本開始,ApplicationEventListeningMessageProducer 實作了 GenericApplicationListener,並且可以設定為不僅接受 ApplicationEvent 類型,還可以接受任何用於處理 Payload 事件的類型(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"/>

在前面的範例中,所有符合 '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 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();
}

傳送 Spring Application Events

若要傳送 Spring ApplicationEvents,請建立 ApplicationEventPublishingMessageHandler 的實例,並將其註冊在端點內。此 MessageHandler 介面的實作也實作了 Spring 的 ApplicationEventPublisherAware 介面,因此充當 Spring Integration 訊息和 ApplicationEvents 之間的橋樑。

為了方便起見,提供了命名空間支援,可以使用 outbound-channel-adapter 元素設定 ApplicationEventPublishingMessageHandler,如下例所示

<int:channel id="eventChannel"/>

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

如果您使用 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"/>

在前面的範例中,發送到 'eventChannel' 通道的所有訊息都會作為 ApplicationEvent 實例發布到在同一個 Spring ApplicationContext 中註冊的任何相關 ApplicationListener 實例。如果訊息的 Payload 是 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);
}

@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();
     }

}

在這種情況下,事件監聽器方法的傳回值會用作 Message 的 Payload,以發布到 eventFromPublisher 通道。有關 @Publisher 的更多資訊,請參閱〈註解驅動設定〉章節。