通道攔截器

訊息架構的優勢之一是能夠以非侵入式方式提供通用行為並捕獲流經系統的訊息的有用資訊。由於 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() 方法。這是因為當訊息傳送到 SubscribableChannel 時,它會根據通道型別直接傳送給零個或多個訂閱者(例如,PublishSubscribeChannel 將訊息傳送給所有訂閱者)。因此,preReceive(…​)postReceive(…​)afterReceiveCompletion(…​) 攔截器方法僅在攔截器應用於 PollableChannel 時才會被呼叫。

Spring Integration 還提供了 Wire Tap 模式的實現。它是一個簡單的攔截器,將 Message 傳送到另一個通道,而不改變現有流程。這對於除錯和監控非常有用。示例請參見 Wire Tap

由於很少需要實現所有攔截器方法,因此介面提供了無操作方法(返回 void 的方法沒有程式碼,返回 Message 的方法按原樣返回 Message,布林方法返回 true)。

攔截器方法的呼叫順序取決於通道型別。如前所述,基於佇列的通道是首先攔截 receive() 方法的唯一通道。此外,傳送和接收攔截之間的關係取決於單獨的傳送方和接收方執行緒的計時。例如,如果接收方在等待訊息時已經阻塞,則順序可能如下:preSendpreReceivepostReceivepostSend。但是,如果接收方在傳送方將訊息放置到通道並已返回後輪詢,則順序將如下:preSendpostSend(一段時間流逝)、preReceivepostReceive。在這種情況下流逝的時間取決於許多因素,因此通常是不可預測的(事實上,receive 可能永遠不會發生)。佇列的型別也起作用(例如,會合與優先順序)。簡而言之,你不能依賴除 preSendpostSend 之前和 preReceivepostReceive 之前之外的順序。

從 Spring Framework 4.1 和 Spring Integration 4.1 開始,ChannelInterceptor 提供了新方法:afterSendCompletion()afterReceiveCompletion()。它們在 send()receive() 呼叫之後被呼叫,無論是否發生任何異常,這允許進行資源清理。請注意,通道在 ChannelInterceptor 列表中以與初始 preSend()preReceive() 呼叫相反的順序呼叫這些方法。

從 5.1 版本開始,全域性通道攔截器現在應用於動態註冊的通道——例如,透過使用 beanFactory.initializeBean() 或使用 Java DSL 時的 IntegrationFlowContext 初始化的 bean。以前,在應用程式上下文重新整理後建立 bean 時,攔截器不適用。

同樣,從 5.1 版本開始,當未收到訊息時,不再呼叫 ChannelInterceptor.postReceive();不再需要檢查 null Message<?>。以前,該方法是會被呼叫的。如果您有一個依賴於先前行為的攔截器,請改用 afterReceiveCompleted(),因為無論是否收到訊息,都會呼叫該方法。

從 5.2 版本開始,ChannelInterceptorAware 已被棄用,轉而使用 Spring Messaging 模組中的 InterceptableChannel,後者現在為了向後相容而擴充套件它。
© . This site is unofficial and not affiliated with VMware.