Spring ApplicationEvent サポート

Spring Integration は、基礎となる Spring Framework で定義されているように、受信および発信 ApplicationEvents のサポートを提供します。Spring のイベントとリスナーのサポートの詳細については、Spring リファレンスマニュアルを参照してください。

この依存関係をプロジェクトに含める必要があります。

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

Spring アプリケーションイベントの受信

イベントを受信してチャネルに送信するには、Spring Integration の ApplicationEventListeningMessageProducer のインスタンスを定義できます。このクラスは、Spring の ApplicationListener インターフェースの実装です。デフォルトでは、受信したすべてのイベントを Spring Integration メッセージとして渡します。イベントの型に基づいて制限するには、"eventTypes" プロパティを使用して、受信するイベント型のリストを設定できます。受信したイベントに「ソース」として Message インスタンスがある場合、その Message はそのまま渡されます。それ以外の場合、SpEL ベースの payloadExpression が提供されている場合、ApplicationEvent インスタンスに対して評価されます。イベントのソースが Message インスタンスではなく、payloadExpression が提供されていない場合、ApplicationEvent 自体がペイロードとして渡されます。

バージョン 4.2 以降、ApplicationEventListeningMessageProducer は GenericApplicationListener を実装し、ApplicationEvent 型だけでなく、ペイロードイベントを処理するための任意の型(Spring Framework 4.2 以降もサポートされています)を受け入れるように構成できます。受け入れられたイベントが PayloadApplicationEvent のインスタンスである場合、その payload はメッセージの送信に使用されます。

便宜上、次の例に示すように、ApplicationEventListeningMessageProducer を inbound-channel-adapter 要素で構成するための名前空間サポートが提供されます。

<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" (オプション)属性で指定された型のいずれかに一致するすべてのアプリケーションコンテキストイベントが、"eventChannel" という名前のメッセージチャネルに Spring Integration メッセージとして配信されます。ダウンストリームコンポーネントが例外をスローすると、失敗したメッセージと例外を含む 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 アプリケーションイベントの送信

Spring ApplicationEvents を送信するには、ApplicationEventPublishingMessageHandler のインスタンスを作成し、エンドポイント内に登録します。MessageHandler インターフェースのこの実装は、Spring の ApplicationEventPublisherAware インターフェースも実装するため、Spring Integration メッセージと ApplicationEvents の間のブリッジとして機能します。

便宜上、次の例に示すように、ApplicationEventPublishingMessageHandler を outbound-channel-adapter 要素で構成するための名前空間サポートが提供されます。

<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" チャネルに送信されるすべてのメッセージは、同じ Spring ApplicationContext 内に登録されている関連する ApplicationListener インスタンスに ApplicationEvent インスタンスとして公開されます。メッセージのペイロードが ApplicationEvent である場合、そのまま渡されます。それ以外の場合、メッセージ自体は MessagingEvent インスタンスにラップされます。

バージョン 4.2 から、MessagingEvent インスタンスにラップする代わりに、publish-payload ブール属性で ApplicationEventPublishingMessageHandler (<int-event:outbound-channel-adapter>)を構成して、アプリケーションコンテキスト payload にパブリッシュすることができます。

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

}

この場合、イベントリスナーメソッドの戻り値は、eventFromPublisher チャネルに発行される Message のペイロードとして使用されます。@Publisher の詳細については、"アノテーション主導の構成" セクションを参照してください。