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

@AroundInvoke在指定注解属性时无法生效的技术问题

解决@AroundInvoke在带属性的拦截器绑定注解下不生效的问题

嘿,这个问题我之前踩过坑!本质是CDI对拦截器绑定的匹配规则导致的——它是基于注解实例的完全相等性来匹配的,不是只看注解类型。

问题根源

你的拦截器类MyInterceptor上标注的是@MyLogger(没有显式指定属性,用默认的skipParams=true),这意味着它只会匹配完全相同的注解实例:也就是目标方法上写@MyLogger()或者@MyLogger的情况(比如你的test1方法)。

而@MyLogger(skipParams=true)虽然属性值和默认一致,但它是一个新的注解实例;@MyLogger(skipParams=false)就更不用说了,这俩都和拦截器上的注解实例不相等,所以拦截器根本不会触发。

解决方案

根据你的需求,有两种处理方式:

方式一:匹配所有带@MyLogger的目标(不管属性值)

这是最常用的场景,只需要给注解的属性加上@Nonbinding注解,告诉CDI在匹配拦截器时忽略这个属性,只判断注解类型即可。

修改后的MyLogger注解:

@Inherited 
@InterceptorBinding 
@Retention(RUNTIME) 
@Target({ TYPE, METHOD })
public @interface MyLogger {
    @Nonbinding // 关键:添加这个注解,让CDI忽略该属性的匹配
    boolean skipParams() default true;
}

这样不管你用@MyLogger、@MyLogger(skipParams=true)还是@MyLogger(skipParams=false),拦截器都会正常生效。而且你依然可以在拦截器中获取属性值来做逻辑判断,比如:

@AroundInvoke
public Object logMethod(InvocationContext joinPoint) throws Exception {
    // 获取方法上的注解
    MyLogger loggerAnno = joinPoint.getMethod().getAnnotation(MyLogger.class);
    // 如果方法上没有,就取类上的
    if (loggerAnno == null) {
        loggerAnno = joinPoint.getTarget().getClass().getAnnotation(MyLogger.class);
    }
    
    boolean skipParams = loggerAnno.skipParams();
    // 这里根据skipParams执行对应的日志逻辑
    System.out.println("是否跳过参数日志:" + skipParams);
    
    return joinPoint.proceed();
}

方式二:按属性值匹配特定拦截器(适合多拦截器场景)

如果你需要针对不同的skipParams值使用不同的拦截器,那就要在对应的拦截器类上显式标注匹配的注解实例。比如:

  • 一个拦截器类标注@MyLogger(skipParams=true),专门处理需要跳过参数的情况
  • 另一个拦截器类标注@MyLogger(skipParams=false),处理需要打印参数的情况

不过这种方式会增加代码冗余,除非有特殊业务需求,否则更推荐方式一。

验证一下

修改后再运行你的test2和test3方法,拦截器的logMethod应该就能正常触发啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:28:32