自定义通知类

除了之前描述的提供的通知类之外,您还可以实现自己的通知类。虽然您可以提供 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;

callback 参数是一个便利手段,可以避免子类直接处理 AOP。调用 callback.execute() 方法会调用消息处理器。

target 参数是为那些需要为特定处理器维护状态的子类提供的,或许可以通过将状态保存在以 target 为键的 Map 中来实现。此特性允许将同一通知应用于多个处理器。RequestHandlerCircuitBreakerAdvice 利用此通知为每个处理器保持熔断器状态。

message 参数是发送给处理器的消息。虽然通知不能在调用处理器之前修改消息本身,但它可以修改载荷(如果载荷具有可变属性)。通常,通知会使用消息进行日志记录,或者在调用处理器之前或之后将消息的副本发送到其他地方。

返回值通常是 callback.execute() 返回的值。然而,通知确实能够修改返回值。请注意,只有 AbstractReplyProducingMessageHandler 实例会返回值。以下示例展示了一个继承 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 对象通过跟踪链中最后调用的通知来维护状态。此状态必须在每次调用时重置。

更多信息请参见 ReflectiveMethodInvocation 的 Javadoc。