チャネルインターセプター

メッセージングアーキテクチャの利点の 1 つは、一般的な動作を提供し、非侵襲的な方法でシステムを通過するメッセージに関する意味のある情報を取得できることです。Message インスタンスは MessageChannel インスタンスとの間で送受信されるため、これらのチャネルは送受信操作をインターセプトする機会を提供します。次のリストに示す ChannelInterceptor 戦略インターフェースは、これらの各操作のメソッドを提供します。

public interface ChannelInterceptor {

    Message<?> preSend(Message<?> message, MessageChannel channel);

    void postSend(Message<?> message, MessageChannel channel, boolean sent);

    void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex);

    boolean preReceive(MessageChannel channel);

    Message<?> postReceive(Message<?> message, MessageChannel channel);

    void afterReceiveCompletion(Message<?> message, MessageChannel channel, Exception ex);
}

インターフェースを実装した後、インターセプターをチャネルに登録するには、次の呼び出しを行うだけです。

channel.addInterceptor(someChannelInterceptor);

Message インスタンスを返すメソッドは、Message の変換に使用できます。また、それ以上の処理を抑止するために 'null' を返すこともできます(もちろん、いずれのメソッドも RuntimeException をスローする可能性があります)。また、preReceive メソッドは false を返して、receive 処理の続行を抑止することもできます。

receive() 呼び出しは PollableChannels にのみ関連することに注意してください。実際、SubscribableChannel インターフェースは receive() メソッドさえ定義していません。これは、Message が SubscribableChannel に送信される場合、チャネルの種類に応じて 0 個以上のサブスクライバーに直接送信されるためです(たとえば、PublishSubscribeChannel はすべてのサブスクライバーに送信します)。preReceive(…​)postReceive(…​)afterReceiveCompletion(…​) インターセプターメソッドは、インターセプターが PollableChannel に適用された場合にのみ呼び出されます。

Spring Integration は、ワイヤータップ (英語) パターンの実装も提供します。これは、既存のフローを変更せずに Message を別のチャネルに送信する単純なインターセプターです。デバッグと監視に非常に役立ちます。ワイヤータップに例を示します。

すべてのインターセプターメソッドを実装する必要はほとんどないため、インターフェースはノーコードメソッドを提供します(void メソッドを返すメソッドにはコードがなく、Message リターンメソッドは Message をそのまま返し、boolean メソッドは true を返します)。

インターセプターメソッドの呼び出し順序は、チャネルの種類によって異なります。前述のように、キューベースのチャネルでは、最初に receive() メソッドがインターセプトされます。また、送信インターセプトと受信インターセプトの関連は、送信側と受信側のスレッドのタイミングによって異なります。例: 受信側がメッセージを待機中にすでにブロックされている場合、順序は preSendpreReceivepostReceivepostSend のようになります。ただし、送信側がチャネルにメッセージを送信してすでに返された後に受信側がポーリングする場合、順序は次のようになります: preSendpostSend (一定の時間が経過)、preReceivepostReceive。このような場合に経過する時間はさまざまな要因によって異なるため、通常は予測できません (実際、receive が発生しないこともあります)。キューの種類もロールを果たします (たとえば、ランデブーと優先順位)。つまり、preSend が postSend に先行し、preReceive が postReceive に先行するという事実以上の順序に頼ることはできません。

Spring Framework 4.1 および Spring Integration 4.1 以降、ChannelInterceptor は新しいメソッド afterSendCompletion() および afterReceiveCompletion() を提供します。発生した例外に関係なく、send()' and 'receive() 呼び出しの後に呼び出され、リソースのクリーンアップが可能になります。チャネルは、最初の preSend() および preReceive() 呼び出しの逆の順序で ChannelInterceptor リストのこれらのメソッドを呼び出すことに注意してください。

バージョン 5.1 以降、グローバルチャネルインターセプターは、Java DSL を使用するときに beanFactory.initializeBean() または IntegrationFlowContext を使用して初期化される Bean を介するなど、動的に登録されたチャネルに適用されるようになりました。以前は、アプリケーションコンテキストのリフレッシュ後に Bean が作成されたときにインターセプターは適用されませんでした。

また、バージョン 5.1 以降、メッセージが受信されないときに ChannelInterceptor.postReceive() が呼び出されなくなりました。null Message<?> をチェックする必要はなくなりました。以前は、メソッドが呼び出されていました。以前の動作に依存するインターセプターがある場合は、代わりに afterReceiveCompleted() を実装してください。これは、メッセージが受信されたかどうかに関係なく、そのメソッドが呼び出されるためです。

バージョン 5.2 から、ChannelInterceptorAware は Spring メッセージングモジュールの InterceptableChannel に代わって非推奨になりました。これは下位互換性のために拡張されています。