Aspectj 编织了带注释的方法和方法调用方法

Aspectj woven both annotated methodA and methodB calling methodA

对于example:I想实现一个AOP重试功能

@Pointcut("@annotation(retryed)")
public void retry(Retry retryed) {}

@Around("retry(retryed)")
public Object process(ProceedingJoinPoint pjp, Retry retryed) throws Throwable {
    Object result = null;
    for (int i = 0; i < 2; i++) {
        result = pjp.proceed();
    }
    return result;
}



@Test
public void test() throws Exception {
    unAnnotatedMethodC();
}
private void unAnnotatedMethodC() {
    System.out.println("unAnnotatedMethodC");
    unAnnotatedMethodB();
}
private void unAnnotatedMethodB() {
    System.out.println("unAnnotatedMethodB");
    annotatedMethodA();
}
@Retry
private void annotatedMethodA() {
    System.out.println("annotatedMethodA");
}

输出:

unAnnotatedMethodC
unAnnotatedMethodB
annotatedMethodA
annotatedMethodA
annotatedMethodA
annotatedMethodA

look the .class file

编织了两次,我希望不是,我想要这样的输出

unAnnotatedMethodC
unAnnotatedMethodB
annotatedMethodA
annotatedMethodA

如何避免这个问题?

您的切入点表达式匹配 executioncall 类型的切入点,这就是您获得双重匹配的原因。 execution 类型切入点匹配方法字节码的位置,而 call 类型切入点将匹配调用这些方法的代码调用点的字节码。您需要将代码限制为 execution 类型的切入点以避免调用 around 建议两次:

@Pointcut("@annotation(retryed) && execution(* *(..))")

请参阅 AspectJ 编程指南中的 call vs execution 以获取更多参考。