简答
虽然您可以制定一个同时匹配 直接带注释的方法和带注释类型的方法的切入点,但您不能您绑定注释值的切入点和/或建议(即在建议代码中使用注释值)。
@Aspect
public class MyAspect {
@Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
public void atExecutionOfAnnotatedMethod() {}
@Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
public void atExecutionOfMethodsOfAnnotatedClass() {}
@Before("atExecutionOfAnnotatedMethod() && @annotation(myAnnotation)")
public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
System.out.println("myAdviceForMethodAnnotation: " + myAnnotation.value());
}
@Before("atExecutionOfMethodsOfAnnotatedClass() && @this(myAnnotation)")
public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
System.out.println("myAdviceForTypeAnnotation: " + myAnnotation.value());
}
// /* the following pointcut will result in "inconsistent binding" errors */
// @Pointcut("(atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)) || (atExecutionOfMethodsOfAnnotatedClass() && @this(myTypeAnnotation))")
// public void combinedPointcut(MyAnnotation myMethodAnnotation, MyAnnotation myTypeAnnotation) {}
}
一些细节
要组合两个单独的切入点(atExecutionOfAnnotatedMethod 和 atExecutionOfMethodsOfAnnotatedClass),我们必须使用 OR (||) 构造。由于 OR 构造不保证两个注解绑定中的任何一个都将出现在通知执行时,它们都会导致编译错误(不一致的绑定)。
您仍然可以在单独的建议中处理这两种情况,您也可以将实际的建议代码委托给一个通用方法以避免重复。在这种情况下,您需要注意 both 类型和方法都使用 @MyAnnotation 注释的情况,因为这将匹配两个切入点,并导致您的方法受到两个建议的双重建议,因此您的常见建议处理代码将执行两次。
两者结合
如果你需要结合这两种情况,同时防止双重通知目标代码,你需要在方法级注解和类级注解之间设置一个优先级。基于特异性原则,我建议走方法级注释优先于类一级的路线。你的方面看起来像这样:
@Aspect
public class MyCombinedAspect {
@Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
public void atExecutionOfAnnotatedMethod() {}
@Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
public void atExecutionOfMethodsOfAnnotatedClass() {}
@Before("atExecutionOfAnnotatedMethod() && !atExecutionOfMethodsOfAnnotatedClass() && @annotation(myAnnotation)")
public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
handleBeforeExecution(joinPoint, myAnnotation);
}
@Before("atExecutionOfMethodsOfAnnotatedClass() && !atExecutionOfAnnotatedMethod() && @this(myAnnotation)")
public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
handleBeforeExecution(joinPoint, myAnnotation);
}
@Before("atExecutionOfMethodsOfAnnotatedClass() && atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)")
public void myAdviceForDoublyAnnotated(JoinPoint joinPoint, MyAnnotation myMethodAnnotation) {
handleBeforeExecution(joinPoint, myMethodAnnotation);
}
protected void handleBeforeExecution(JoinPoint joinPoint, MyAnnotation myAnnotation) {
System.out.println(myAnnotation.value());
}