如何在Spring AOP中拦截方法上的元注解(注解的注解)
Spring AOP 方法上元注解拦截的正确切点表达式
已经实现了Spring AOP对类上元注解的拦截,但现在需要拦截方法上的元注解,现有切面表达式仅能作用于类,尝试多种写法都报“切面表达式无法解析”错误,以下是可行的解决方案。
原注解与切面代码
MetaAnnotation元注解
package de.scrum_master.app; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target({ TYPE }) public @interface MetaAnnotation {}
MyAnnotation注解(标注了元注解)
package de.scrum_master.app; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target({ TYPE }) @MetaAnnotation public @interface MyAnnotation {}
原切面类
package de.scrum_master.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class MetaAnnotationInterceptor { @Before( "execution(* *(..)) && (" + "within(@de.scrum_master.app.MetaAnnotation *) || " + "within(@(@de.scrum_master.app.MetaAnnotation *) *)" + ")" ) public void myAdvice(JoinPoint thisJoinPoint){ System.out.println(thisJoinPoint); } }
解决方案
第一步:修改注解的Target范围
原代码中两个注解的@Target仅设置了TYPE,只能标注在类上。要支持方法级标注,需给注解添加METHOD类型:
修改后的MetaAnnotation
package de.scrum_master.app; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target({ TYPE, METHOD }) // 添加METHOD支持 public @interface MetaAnnotation {}
修改后的MyAnnotation
package de.scrum_master.app; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target({ TYPE, METHOD }) // 添加METHOD支持 @MetaAnnotation public @interface MyAnnotation {}
第二步:编写支持方法上元注解的切点表达式
正确的表达式需要覆盖四种拦截场景:类直接标注元注解、类标注的注解被元注解修饰、方法直接标注元注解、方法标注的注解被元注解修饰。
修改后的切面类代码:
package de.scrum_master.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class MetaAnnotationInterceptor { @Before( "execution(* *(..)) && (" + // 拦截类直接标注MetaAnnotation的所有方法 "within(@de.scrum_master.app.MetaAnnotation *) || " + // 拦截类标注了被MetaAnnotation修饰的注解的所有方法 "within(@(@de.scrum_master.app.MetaAnnotation *) *) || " + // 拦截方法直接标注MetaAnnotation的情况 "@annotation(de.scrum_master.app.MetaAnnotation) || " + // 拦截方法标注了被MetaAnnotation修饰的注解的情况 "@annotation(@de.scrum_master.app.MetaAnnotation *)" + ")" ) public void myAdvice(JoinPoint thisJoinPoint){ System.out.println(thisJoinPoint); } }
内容的提问来源于stack exchange,提问作者White
相关产品推荐
相关产品推荐

