Handling Message Advice

the introduction to this section 中所讨论的,请求处理程序通知链中的通知对象仅应用于当前端点,而不是下游流程(如果有)。对于产生回复的 MessageHandler 对象(例如扩展 AbstractReplyProducingMessageHandler 的对象),通知应用于内部方法: handleRequestMessage() (从 MessageHandler.handleMessage() 调用)。对于其他消息处理程序,通知应用于 MessageHandler.handleMessage()

As discussed in the introduction to this section, advice objects in a request handler advice chain are applied to just the current endpoint, not the downstream flow (if any). For MessageHandler objects that produce a reply (such as those that extend AbstractReplyProducingMessageHandler), the advice is applied to an internal method: handleRequestMessage() (called from MessageHandler.handleMessage()). For other message handlers, the advice is applied to MessageHandler.handleMessage().

在某些情况下,即使消息处理程序是 AbstractReplyProducingMessageHandler ,也必须将通知应用于 handleMessage 方法。例如,idempotent receiver 可能会返回 null ,如果处理程序的 replyRequired 属性设置为 true ,这会导致异常。另一个示例是 BoundRabbitChannelAdvice ,请参阅 Strict Message Ordering

There are some circumstances where, even if a message handler is an AbstractReplyProducingMessageHandler, the advice must be applied to the handleMessage method. For example, the idempotent receiver might return null, which would cause an exception if the handler’s replyRequired property is set to true. Another example is the BoundRabbitChannelAdvice — see Strict Message Ordering.

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

Starting with version 4.3.1, a new HandleMessageAdvice interface and its base implementation (AbstractHandleMessageAdvice) have been introduced. Advice objects that implement HandleMessageAdvice are always applied to the handleMessage() method, regardless of the handler type.

了解当应用于返回响应的处理程序时,HandleMessageAdvice 实现(如 idempotent receiver)与 adviceChain 分离并正确应用于 MessageHandler.handleMessage() 方法非常重要。

It is important to understand that HandleMessageAdvice implementations (such as idempotent receiver), when applied to a handlers that return responses, are dissociated from the adviceChain and properly applied to the MessageHandler.handleMessage() method.

由于此解关联,所以不会遵守 advice 链顺序。

Because of this disassociation, the advice chain order is not honored.

考虑以下配置:

Consider the following configuration:

<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> 中调用的 before。为了保持顺序,您应该遵循标准的 Spring AOP 配置方法,并将端点 id.handler 后缀一起使用以获取目标 MessageHandler bean。请注意,在这种情况下,整个下游流程都在事务范围内。

In the preceding example, the <tx:advice> is applied to the AbstractReplyProducingMessageHandler.handleRequestMessage(). However, myHandleMessageAdvice is applied for to MessageHandler.handleMessage(). Therefore, it is invoked before the <tx:advice>. To retain the order, you should follow the standard Spring AOP configuration approach and use an endpoint id together with the .handler suffix to obtain the target MessageHandler bean. Note that, in that case, the entire downstream flow is within the transaction scope.

对于不返回响应的 MessageHandler,将保留建议链的顺序。

In the case of a MessageHandler that does not return a response, the advice chain order is retained.

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

Starting with version 5.3, the HandleMessageAdviceAdapter is provided to apply any MethodInterceptor for the MessageHandler.handleMessage() method and, therefore, the whole sub-flow. For example, a RetryOperationsInterceptor could be applied to the whole sub-flow starting from some endpoint; this is not possible, by default, because the consumer endpoint applies advices only to the AbstractReplyProducingMessageHandler.RequestHandler.handleRequestMessage().