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

Spring AOP 6.1+中无法获取Groovy类方法参数名的解决方案咨询

解决方案:Spring 6.1中AOP获取方法参数名的替代方案

核心问题原因

Spring 6.1移除了LocalVariableTableParameterNameDiscoverer,原有的MethodSignature.getParameterNames()依赖该实现,导致即使开启-parameters编译参数也可能返回null。当前Spring默认使用DefaultParameterNameDiscoverer,需主动适配该实现来获取参数名。

步骤1:确保编译时启用-parameters参数

这是反射获取参数名的基础,必须配置:

  • Maven:在pom.xml的maven-compiler-plugin中添加配置
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.11.0</version>
        <configuration>
            <source>17</source> <!-- 替换为你的JDK版本 -->
            <target>17</target>
            <parameters>true</parameters> <!-- 关键配置 -->
        </configuration>
    </plugin>
    
  • Gradle:在build.gradle中添加
    compileJava {
        options.parameters = true
    }
    
  • IDEA:打开File > Settings > Build, Execution, Deployment > Compiler > Java Compiler,勾选Store information about method parameters (usable via reflection)

步骤2:在切面中使用DefaultParameterNameDiscoverer获取参数名

不再依赖MethodSignature.getParameterNames(),手动通过Spring推荐的实现获取:

@Aspect
@Component
public class CustomAnnotationAspect {
    private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

    @Before("@annotation(customAnnotation)")
    public void handleSecurityLogic(JoinPoint joinPoint, CustomAnnotation customAnnotation) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method targetMethod = signature.getMethod();
        
        // 获取参数名数组
        String[] paramNames = parameterNameDiscoverer.getParameterNames(targetMethod);
        if (paramNames == null) {
            throw new IllegalStateException("无法获取方法参数名,请检查编译参数是否开启-parameters");
        }

        Object[] methodArgs = joinPoint.getArgs();
        // 示例:匹配注解中指定的projectId参数
        int projectIdIdx = Arrays.asList(paramNames).indexOf(customAnnotation.projectIdParameter());
        if (projectIdIdx != -1) {
            String projectId = (String) methodArgs[projectIdIdx];
            // 执行你的安全校验逻辑
        }

        // 示例:处理SpEL表达式(如#userEntity.id)
        SpelExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = new StandardEvaluationContext();
        for (int i = 0; i < paramNames.length; i++) {
            context.setVariable(paramNames[i], methodArgs[i]);
        }
        Object userId = parser.parseExpression(customAnnotation.userIdParameter()).getValue(context);
        // 基于userId的安全逻辑
    }
}

步骤3:解决偶发失效问题

  • 强制清理构建缓存:执行mvn clean install时,确保删除target目录,避免旧编译产物干扰
  • IDEA运行配置检查:在Run/Debug Configurations中,勾选Build project before running,确保每次运行前都重新编译
  • 排查Bean冲突:检查Spring容器中是否存在自定义的ParameterNameDiscoverer Bean,若有需确保其兼容DefaultParameterNameDiscoverer的逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:33:22