消息 Advice 处理

正如本节导言中所讨论的,请求处理器 advice 链中的 advice 对象仅应用于当前端点,而不应用于下游流(如果有的话)。对于产生回复的 MessageHandler 对象(例如那些扩展 AbstractReplyProducingMessageHandler 的对象),advice 应用于内部方法:handleRequestMessage()(由 MessageHandler.handleMessage() 调用)。对于其他消息处理器,advice 应用于 MessageHandler.handleMessage()

在某些情况下,即使消息处理器是 AbstractReplyProducingMessageHandler,advice 也必须应用于 handleMessage 方法。例如,幂等接收器可能返回 null,如果处理器的 replyRequired 属性设置为 true,这将导致异常。另一个例子是 BoundRabbitChannelAdvice — 请参阅严格消息排序

从版本 4.3.1 开始,引入了新的 HandleMessageAdvice 接口及其基础实现(AbstractHandleMessageAdvice)。实现 HandleMessageAdviceAdvice 对象始终应用于 handleMessage() 方法,无论处理程序类型如何。

理解 HandleMessageAdvice 实现(例如幂等接收器)应用于返回响应的处理程序时,会与 adviceChain 分离并正确应用于 MessageHandler.handleMessage() 方法,这一点很重要。

由于这种分离,advice 链顺序将不会得到遵循。

考虑以下配置

<some-reply-producing-endpoint ... >
    <int:request-handler-advice-chain>
        <tx:advice ... />
        <ref bean="myHandleMessageAdvice" />
    </int:request-handler-advice-chain>
</some-reply-producing-endpoint>

在前面的示例中,<tx:advice> 应用于 AbstractReplyProducingMessageHandler.handleRequestMessage()。但是,myHandleMessageAdvice 应用于 MessageHandler.handleMessage()。因此,它在 <tx:advice> 之前被调用。为了保留顺序,您应该遵循标准的Spring AOP配置方法,并使用端点 id.handler 后缀来获取目标 MessageHandler bean。请注意,在这种情况下,整个下游流都处于事务范围内。

对于不返回响应的 MessageHandler,advice 链顺序得到保留。

从版本 5.3 开始,提供了 HandleMessageAdviceAdapter,用于将任何 MethodInterceptor 应用于 MessageHandler.handleMessage() 方法,从而应用于整个子流。例如,可以将 RetryOperationsInterceptor 应用于从某个端点开始的整个子流;默认情况下这是不可能的,因为消费者端点仅将 advice 应用于 AbstractReplyProducingMessageHandler.RequestHandler.handleRequestMessage()