Custom Advice Classes

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

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

/**
 * 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() 方法会调用消息处理程序。

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

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

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

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 来维护状态。对于每次调用都必须重置此状态。 有关更多信息,请参阅 ReflectiveMethodInvocation JavaDoc。