Custom Advice Classes

除了前面描述的提供的 advice 类 xref:handler-advice/classes.adoc 之外,您还可以实现自己的 advice 类。虽然您可以提供 org.aopalliance.aop.Advice(通常为 org.aopalliance.intercept.MethodInterceptor)的任何实现,但我们通常建议您继承 o.s.i.handler.advice.AbstractRequestHandlerAdvice。这样可以避免编写低级别的面向方面编程代码,并提供专门针对在此环境中使用而定制的起点。

In addition to the provided advice classes described earlier, you can implement your own advice classes. While you can provide any implementation of org.aopalliance.aop.Advice (usually org.aopalliance.intercept.MethodInterceptor), we generally recommend that you subclass o.s.i.handler.advice.AbstractRequestHandlerAdvice. This has the benefit of avoiding the writing of low-level aspect-oriented programming code as well as providing a starting point that is specifically tailored for use in this environment.

子类需要实现 doInvoke() 方法,其定义如下:

Subclasses need to implement the doInvoke() method, the definition of which follows:

/**
 * Subclasses implement this method to apply behavior to the {@link MessageHandler} callback.execute()
 * invokes the handler method and returns its result, or null).
 * @param callback Subclasses invoke the execute() method on this interface to invoke the handler method.
 * @param target The target handler.
 * @param message The message that will be sent to the handler.
 * @return the result after invoking the {@link MessageHandler}.
 * @throws Exception
 */
protected abstract Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception;

回调参数是一种便利措施,可避免直接处理 AOP 的子类。调用 callback.execute() 方法会调用消息处理程序。

The callback parameter is a convenience to avoid subclasses that deal with AOP directly. Invoking the callback.execute() method invokes the message handler.

为需要维护特定处理程序状态的子类提供 target 参数,或许可以通过在以目标为键的 Map 中维护该状态。此特性允许将同一 advice 应用于多个处理程序。RequestHandlerCircuitBreakerAdvice 使用此 advice 为每个处理程序保留断路器状态。

The target parameter is provided for those subclasses that need to maintain state for a specific handler, perhaps by maintaining that state in a Map keyed by the target. This feature allows the same advice to be applied to multiple handlers. The RequestHandlerCircuitBreakerAdvice uses advice this to keep circuit breaker state for each handler.

message 参数是发送到处理程序的消息。虽然 advice 在调用处理程序之前无法修改消息,但它可以修改有效内容(如果它具有可变属性)。通常,advice 会使用消息进行日志记录或在调用处理程序之前或之后将消息副本发送到某个位置。

The message parameter is the message sent to the handler. While the advice cannot modify the message before invoking the handler, it can modify the payload (if it has mutable properties). Typically, an advice would use the message for logging or to send a copy of the message somewhere before or after invoking the handler.

返回值通常是 callback.execute() 返回的值。但是,advice 确实有能力修改返回值。请注意,只有 AbstractReplyProducingMessageHandler 实例才会返回值。以下示例显示了扩展 AbstractRequestHandlerAdvice 的自定义 advice 类:

The return value would normally be the value returned by callback.execute(). However, the advice does have the ability to modify the return value. Note that only AbstractReplyProducingMessageHandler instances return values. The following example shows a custom advice class that extends AbstractRequestHandlerAdvice:

public class MyAdvice extends AbstractRequestHandlerAdvice {

    @Override
    protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
        // add code before the invocation
        Object result = callback.execute();
        // add code after the invocation
        return result;
    }
}

除了 execute() 方法之外,ExecutionCallback 还提供了另一个方法:cloneAndExecute()。必须在单个 doInvoke() 执行中可能多次调用该调用(例如,在 RequestHandlerRetryAdvice 中)的情况下使用此方法。这是必需的,因为 Spring AOP org.springframework.aop.framework.ReflectiveMethodInvocation 对象通过跟踪链中最后调用的 advice 来维护状态。对于每次调用都必须重置此状态。

In addition to the execute() method, ExecutionCallback provides an additional method: cloneAndExecute(). This method must be used in cases where the invocation might be called multiple times within a single execution of doInvoke(), such as in the RequestHandlerRetryAdvice. This is required because the Spring AOP org.springframework.aop.framework.ReflectiveMethodInvocation object maintains state by keeping track of which advice in a chain was last invoked. This state must be reset for each call.

有关更多信息,请参阅 ReflectiveMethodInvocation JavaDoc。

For more information, see the ReflectiveMethodInvocation Javadoc.