@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
相关产品推荐
相关产品推荐

