|
对于最新稳定版本,请使用 Spring Integration 7.0.0! |
通道拦截器
消息架构的一个优势是能够以非侵入式方式提供通用行为,并捕获通过系统传递的消息的有意义信息。
自从......消息实例发送和接收消息频道这些信道为拦截发送和接收作提供了机会。
这通道拦截者策略界面(如下列表所示)为这些作提供了方法:
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);
返回消息实例可用于变换消息或者可以返回“null”以阻止进一步处理(当然,任何方法都可能抛出运行异常).
另外,还有预接收方法可以返回false以防止接收作继续。
请记住接收()调用仅在可投票频道.
事实上,订阅频道接口甚至没有定义接收()方法。
原因在于当消息被发送到订阅频道,根据频道类型,直接发送给零个或多个用户(例如,
一个发布订阅频道发送给所有订阅者)。
因此,preReceive(...),postReceive(...)和afterReceiveCompletion(...)拦截器方法仅在被应用到一个Pollable频道. |
Spring Integration 还提供了线分流模式的实现。
它是一种简单的拦截器,发送消息在不改变现有水流的情况下,转移到另一条渠道。
它在调试和监控方面非常有用。
一个例子在《窃听》中有所展示。
由于很少需要实现所有拦截方法,接口提供无作方法(返回无效方法没有代码,消息- 返回方法 返回消息原样,以及布尔方法返回true).
拦截方法的调用顺序取决于信道类型。
如前所述,基于队列的信道是唯一具有接收()方法首先被截获。
此外,发送和接收拦截之间的关系取决于发送端和接收端线程的时序。
例如,如果接收方在等待消息时已被阻塞,顺序可能如下:preSend,预接收,postReceive,postSend.
然而,如果接收方在发送方在信道上放置消息并已返回后进行轮询,顺序如下:preSend,postSend(时间过时),预接收,postReceive.
在这种情况下,时间的流逝取决于多种因素,因此通常不可预测(事实上,接收可能永远不会发生)。
排队类型也起作用(例如,会合与优先级)。
简而言之,你不能仅凭命令,仅仅因为preSend之前postSend和预接收之前postReceive. |
从 Spring Framework 4.1 和 Spring Integration 4.1 开始,通道拦截者提供新方法:afterSendCompletion()和afterReceiveCompletion().
它们在之后被调用send()' 和 'receive()调用,无论是否提出异常,都允许资源清理。
注意信道调用这些方法于通道拦截者列表按首字母的倒序排列preSend()和preReceive()调用。
从版本5.1开始,全局信道拦截器适用于动态注册信道——例如通过beanFactory.initializeBean()或集成流上下文当使用 Java DSL 时。
此前,在应用上下文刷新后创建豆子时,不会应用拦截器。
另外,从5.1版本开始,ChannelInterceptor.postReceive()当未收到消息时不再调用;不再需要检查零 留言<?>.
此前,该方法被称为
如果你有一个依赖之前行为的拦截器,那就实现afterReceiveCompleted()而是因为无论消息是否被接收,都会调用该方法。
从5.2版本开始,频道拦截者意识被弃用,取而代之的是拦截频道来自Spring Messaging模块,现已扩展以实现向后兼容。 |