通道拦截器
消息架构的优点之一是能够以非侵入式方式提供通用行为并捕获有关通过系统的消息的有意义的信息。
由于 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
以阻止接收操作继续进行。
请记住, |
Spring Integration 还提供了 Wire Tap 模式的实现。
它是一个简单的拦截器,将 Message
发送到另一个通道,而不改变现有流程。
它对于调试和监控非常有用。
Wire Tap 中显示了一个示例。
由于很少需要实现所有拦截器方法,因此接口提供了无操作方法(那些返回 void
方法的没有代码,返回 Message
的方法按原样返回 Message
,boolean
方法返回 true
)。
拦截器方法的调用顺序取决于通道类型。
如前所述,基于队列的通道是首先拦截 |
从 Spring Framework 4.1 和 Spring Integration 4.1 开始,ChannelInterceptor
提供了新方法:afterSendCompletion()
和 afterReceiveCompletion()
。
它们在 send()
和 receive()
调用之后被调用,无论是否抛出任何异常,这允许进行资源清理。
请注意,通道以与初始 preSend()
和 preReceive()
调用相反的顺序在 ChannelInterceptor
列表中调用这些方法。
从 5.1 版本开始,全局通道拦截器现在应用于动态注册的通道——例如通过使用 beanFactory.initializeBean()
或在使用 Java DSL 时通过 IntegrationFlowContext
初始化的 bean。
以前,当在应用程序上下文刷新后创建 bean 时,拦截器不会应用。
此外,从 5.1 版本开始,当没有收到消息时,不再调用 ChannelInterceptor.postReceive()
;不再需要检查 null
Message<?>
。
以前,该方法会被调用。
如果您的拦截器依赖于以前的行为,请改为实现 afterReceiveCompleted()
,因为无论是否收到消息,该方法都会被调用。
从 5.2 版本开始, |