消息传递体系结构的优点之一是能够提供通用行为,并以非侵入性方式捕获有关通过系统的消息的有意义的信息。
由于实例是发送到实例和从实例接收的,因此这些通道提供了拦截发送和接收操作的机会。
以下清单中显示的策略接口为每个操作提供了方法: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);
返回实例的方法可用于转换 或 可以返回 'null' 以防止进一步处理(当然,任何方法都可以抛出 )。
此外,该方法可以返回以防止接收操作继续进行。Message
Message
RuntimeException
preReceive
false
请记住,调用仅与 相关。
事实上,该接口甚至没有定义方法。
这样做的原因是,当 a 被发送到 时,它会直接发送到零个或多个订阅者,具体取决于频道的类型(例如,
a 发送给其所有订户)。
因此,仅当侦听器应用于 时,才会调用 、 和 侦听器方法。receive() PollableChannels SubscribableChannel receive() Message SubscribableChannel PublishSubscribeChannel preReceive(…) postReceive(…) afterReceiveCompletion(…) PollableChannel |
请记住,调用仅与 相关。
事实上,该接口甚至没有定义方法。
这样做的原因是,当 a 被发送到 时,它会直接发送到零个或多个订阅者,具体取决于频道的类型(例如,
a 发送给其所有订户)。
因此,仅当侦听器应用于 时,才会调用 、 和 侦听器方法。receive() PollableChannels SubscribableChannel receive() Message SubscribableChannel PublishSubscribeChannel preReceive(…) postReceive(…) afterReceiveCompletion(…) PollableChannel |
Spring Integration 还提供了 Wire Tap 模式的实现。
它是一个简单的拦截器,可以将它发送到另一个通道,而不会以其他方式改变现有流。
它对于调试和监视非常有用。
Wire Tap 中显示了一个示例。Message
由于很少需要实现所有拦截器方法,因此接口提供了 no-op 方法(返回的方法没有代码,-return 方法按原样返回,方法返回)。void
Message
Message
boolean
true
拦截器方法的调用顺序取决于信道的类型。
如前所述,基于队列的通道是唯一首先截获该方法的通道。
此外,发送和接收拦截之间的关系取决于单独的发送方和接收方线程的计时。
例如,如果接收方在等待消息时已被阻止,则顺序可能如下:、。
但是,如果接收方在发送方在通道上放置消息并已返回后进行轮询,则顺序如下:、(有时经过)、、.
在这种情况下,经过的时间取决于许多因素,因此通常是不可预测的(事实上,接收可能永远不会发生)。
队列的类型也起着一定的作用(例如,会合与优先级)。
简而言之,您不能依赖 之前和之前的事实之外的顺序。receive() preSend preReceive postReceive postSend preSend postSend preReceive postReceive preSend postSend preReceive postReceive |
拦截器方法的调用顺序取决于信道的类型。
如前所述,基于队列的通道是唯一首先截获该方法的通道。
此外,发送和接收拦截之间的关系取决于单独的发送方和接收方线程的计时。
例如,如果接收方在等待消息时已被阻止,则顺序可能如下:、。
但是,如果接收方在发送方在通道上放置消息并已返回后进行轮询,则顺序如下:、(有时经过)、、.
在这种情况下,经过的时间取决于许多因素,因此通常是不可预测的(事实上,接收可能永远不会发生)。
队列的类型也起着一定的作用(例如,会合与优先级)。
简而言之,您不能依赖 之前和之前的事实之外的顺序。receive() preSend preReceive postReceive postSend preSend postSend preReceive postReceive preSend postSend preReceive postReceive |
从 Spring Framework 4.1 和 Spring Integration 4.1 开始,提供了新的方法: 和 .
它们在调用后调用,而不考虑引发的任何异常,从而允许资源清理。
请注意,通道以初始和调用的相反顺序调用列表中的这些方法。ChannelInterceptor
afterSendCompletion()
afterReceiveCompletion()
send()' and 'receive()
ChannelInterceptor
preSend()
preReceive()
从 V5.1 开始,全局通道拦截器现在适用于动态注册的通道,例如通过使用 Java DSL 或使用 Java DSL 时初始化的 Bean。
以前,在刷新应用程序上下文后创建 Bean 时,不会应用拦截器。beanFactory.initializeBean()
IntegrationFlowContext
此外,从版本 5.1 开始,当未收到任何消息时,不再调用;不再需要检查 .
以前,调用了该方法。
如果您有一个依赖于先前行为的拦截器,请改为实现,因为无论是否收到消息,都会调用该方法。ChannelInterceptor.postReceive()
null
Message<?>
afterReceiveCompleted()
从版本 5.2 开始,Spring Messaging 模块中已弃用 for the Spring Messaging 模块,它现在扩展了该模块以实现向后兼容性。ChannelInterceptorAware InterceptableChannel |
从版本 5.2 开始,Spring Messaging 模块中已弃用 for the Spring Messaging 模块,它现在扩展了该模块以实现向后兼容性。ChannelInterceptorAware InterceptableChannel |