You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在AOP Around通知中如何正确处理返回Callable的方法?

问题根因

你当前的写法确实会导致call()方法执行两次:一次是切面内主动调用,另一次是Spring MVC处理异步返回值时的内部调用,这就是接口耗时翻倍的直接原因。

最优改造方案

不需要主动调用call(),只需对返回的Callable做一层包装,把日志逻辑嵌入到包装后的call()方法中,再把包装后的Callable返回给Spring MVC即可,改造成本极低,原有日志逻辑可以完全复用。
改造后的切面代码如下:

@Around("...")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    Object result = joinPoint.proceed();
    if (!(result instanceof Callable<?>)) {
        // 原有同步返回的日志逻辑无需修改
        long cost = System.currentTimeMillis() - startTime;
        // 记录日志:耗时、响应结果、状态码等
        return result;
    } else {
        Callable<?> originalCallable = (Callable<?>) result;
        // 包装原有Callable,嵌入日志逻辑
        return (Callable<Object>) () -> {
            Object callableResult = originalCallable.call();
            long cost = System.currentTimeMillis() - startTime;
            // 此处复用原有日志逻辑,callableResult就是实际响应结果
            return callableResult;
        };
    }
}

该方案的原理是仅对Callable做功能增强,不会提前执行业务逻辑,Spring MVC后续处理异步请求时只会调用一次包装后的call()方法,同时完成业务逻辑执行和日志记录,没有额外性能损耗。

备选方案

如果不想在切面中处理异步逻辑,也可以使用Spring MVC自带的ResponseBodyAdvice统一拦截所有响应结果,无需关心控制器返回值类型,Spring会在响应返回给客户端前把最终响应体传入回调方法,直接在这里执行日志逻辑即可,示例代码如下:

@ControllerAdvice
public class GlobalResponseLogAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 配置对所有返回值生效
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, 
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType, 
                                  ServerHttpRequest request, ServerHttpResponse response) {
        // body就是最终的响应结果,直接在此处执行日志记录逻辑即可
        return body;
    }
}

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:45:02