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

メッセージングアーキテクチャの利点の 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 処理の続行を抑止することもできます。

Keep in mind that receive() calls are only relevant for PollableChannels. In fact, the SubscribableChannel interface does not even define a receive() method. The reason for this is that when a Message is sent to a SubscribableChannel, it is sent directly to zero or more subscribers, depending on the type of channel, (for example, a PublishSubscribeChannel sends to all of its subscribers). Therefore, the preReceive(…​)postReceive(…​)afterReceiveCompletion(…​) interceptor methods are invoked only when the interceptor is applied to a PollableChannel.

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

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

The order of invocation for the interceptor methods depends on the type of channel. As described earlier, the queue-based channels are the only ones where the receive() method is intercepted in the first place. Additionally, the relationship between send and receive interception depends on the timing of the separate sender and receiver threads. For example, if a receiver is already blocked while waiting for a message, the order could be as follows: preSendpreReceivepostReceivepostSend. However, if a receiver polls after the sender has placed a message on the channel and has already returned, the order would be as follows: preSendpostSend (some-time-elapses), preReceivepostReceive. The time that elapses in such a case depends on a number of factors and is therefore generally unpredictable (in fact, the receive may never happen). The type of queue also plays a role, (for example, rendezvous versus priority). In short, you cannot rely on the order beyond the fact that preSend precedes postSend and preReceive precedes 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 に代わって非推奨になりました。これは下位互換性のために拡張されています。