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

AspectJ/Spring AOP拦截方法时如何获取调用方方法的入参

问题前提说明

你当前的用法存在两个核心限制:

  1. 默认Spring AOP是基于动态代理实现,仅能拦截Spring容器托管的Bean的方法执行,你代码中的Ent是自行new出来的实例,execution切入点根本无法拦截到getSth方法的执行。
  2. Spring AOP仅支持execution类型切入点,不支持call切入点,也无法直接获取调用方方法的上下文参数。

所以最优解是切换到AspectJ实现,无需修改业务代码即可实现需求。


方案一:使用AspectJ(推荐,无侵入,性能稳定)

首先需要为项目开启AspectJ的编译时织入(CTW)或者加载时织入(LTW),即可支持call切入点和调用方上下文获取。

切面代码实现

如果调用getSth的上层方法签名统一(都是入参为Integer的shouldDoSthAndCallMethodGetSth),可以直接绑定参数:

@Aspect
public class GettingSthAdvisor {

    @Before("call(* com.example.demo.aspects.Ent.getSth()) && withincode(* com.example.demo..*.shouldDoSthAndCallMethodGetSth(Integer)) && args(callerParam)")
    public void beforeGetSthCall(Integer callerParam) {
        // callerParam就是你要的666、999这类上层入参
        // 你的参数处理逻辑
    }
}

如果上层调用方方法名不统一,可通过封闭连接点直接获取所有上层方法入参:

@Aspect
public class GettingSthAdvisor {

    @Around("call(* com.example.demo.aspects.Ent.getSth())")
    public Object aroundGetSthCall(ProceedingJoinPoint pjp) throws Throwable {
        // 获取上层调用方法的所有入参数组
        Object[] callerArgs = pjp.getEnclosingJoinPoint().getArgs();
        // 按业务逻辑提取需要的参数即可,比如提取第一个Integer类型参数
        for (Object arg : callerArgs) {
            if (arg instanceof Integer) {
                Integer callerParam = (Integer) arg;
                // 你的参数处理逻辑
                break;
            }
        }
        return pjp.proceed();
    }
}

方案二:基于Spring AOP实现(侵入性高,仅适合不愿意引入AspectJ织入的场景)

需要修改两处核心逻辑:

  1. 把Ent类交给Spring容器托管,禁止自行new实例,否则无法被Spring AOP拦截
  2. 通过ThreadLocal透传参数,需要修改所有调用方的业务代码:

1. 定义参数传递的ThreadLocal工具类

public class CallerParamHolder {
    private static final ThreadLocal<Integer> PARAM_HOLDER = new ThreadLocal<>();

    public static void set(Integer param) {
        PARAM_HOLDER.set(param);
    }

    public static Integer get() {
        return PARAM_HOLDER.get();
    }

    public static void remove() {
        PARAM_HOLDER.remove();
    }
}

2. 修改所有调用方代码,透传参数

public class A {
    // 注入Spring托管的Ent实例
    @Autowired
    private Ent ent;

    public void shouldDoSthAndCallMethodGetSth(Integer a) {
        CallerParamHolder.set(a);
        try {
            ent.getSth();
        } finally {
            // 必须在finally中清除,避免线程复用导致参数串读
            CallerParamHolder.remove();
        }
    }
}

3. 切面中获取参数

@Aspect
@Component
public class GettingSthAdvisor {

    @Around("execution(* com.example.demo.aspects.Ent.getSth())")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Integer callerParam = CallerParamHolder.get();
        // 你的参数处理逻辑
        return pjp.proceed();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:39:02