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

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

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

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

インターセプターメソッドの呼び出しの順序は、チャネルの型によって異なります。前に説明したように、キューベースのチャネルは、receive() メソッドが最初にインターセプトされる唯一のチャネルです。さらに、送信インターセプトと受信インターセプトの関連は、個別の送信側スレッドと受信側スレッドのタイミングによって異なります。例: メッセージの待機中に受信者がすでにブロックされている場合、順序は次のようになります: preSendpreReceivepostReceivepostSend。ただし、送信者がチャネルにメッセージを送信してすでに戻ってきた後に受信者がポーリングする場合、順序は次のようになります: preSendpostSend (しばらく経過)、preReceivepostReceive。このような場合に経過する時間は多くの要因に依存するため、一般的に予測できません(実際、受信は発生しない可能性があります)。キューの型もロールを果たします(たとえば、ランデブーと優先度)。つまり、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() が呼び出されなくなりました。nullMessage<?> をチェックする必要はなくなりました。以前は、メソッドが呼び出されていました。以前の動作に依存するインターセプターがある場合は、代わりに afterReceiveCompleted() を実装してください。これは、メッセージが受信されたかどうかに関係なく、そのメソッドが呼び出されるためです。

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