简体   繁体   English

如何使用 AspectJ 在 java 中实现重试机制

[英]How to implement Retry mechanism in java using AspectJ

I am trying to implement Retry mechanism using AspectJ .我正在尝试使用AspectJ实现重试机制。 If a method throws any exception AspectJ should invoke method once again.如果方法抛出任何异常, AspectJ应该再次调用方法。

Here is my code:这是我的代码:

Retry annotation:重试注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Retry {
    int retryCount();
}

Retry aspect:重试方面:

@Aspect
public class RetryAspect {
    @Around("@annotation(main.Retry)")
    public Object profile(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object response = null;
        Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
        Retry annotation = method.getAnnotation(Retry.class);
        int retryCount = annotation.retryCount();
        boolean successfull = false;
        do{
            try {
                response = proceedingJoinPoint.proceed();
                successfull = true;
            }catch(Exception ex){
                retryCount--;
                if(retryCount < 0){
                    throw ex;
                }
            }
        }while(!successfull);
        return response;
    }
}

main method:主要方法:

public class Main {

    @Retry(retryCount = 1)
    public int method1() throws Exception  {
        System.out.println("method 1");
        throw new Exception();
    }

    public static void main(String[] args) throws Exception {
        Main m = new Main();
        boolean successfull = false;
        m.method1();
        System.out.println("Exit main");
    }
}

If my understanding is correct program should print "method 1" twice and throw exception.But "method 1" is getting printed 4 times.如果我的理解是正确的,程序应该打印两次“方法 1”并抛出异常。但是“方法 1”被打印了 4 次。 Here is output:这是 output:

method 1
method 1
method 1
method 1
Exception in thread "main" java.lang.Exception
    at main.Main.method1_aroundBody0(Main.java:8)
    at main.Main.method1_aroundBody1$advice(Main.java:24)
    at main.Main.method1(Main.java:1)
    at main.Main.method1_aroundBody2(Main.java:14)
    at main.Main.method1_aroundBody3$advice(Main.java:24)
    at main.Main.main(Main.java:14)

Please mention if there is any wrong with my implementation.请提及我的实施是否有任何问题。

You use AspectJ, not Spring AOP, which is why your pointcut matches both您使用 AspectJ,而不是 Spring AOP,这就是为什么您的切入点同时匹配

  • call() (the source of the method call) and call() (方法调用的来源)和
  • execution() (the target method itself) execution() (目标方法本身)

joinpoints, thus you see 4 instead of 2 log outputs.连接点,因此您会看到 4 个而不是 2 个日志输出。 You could have found out by yourself easily if you would have made it a habit to always print the full joinpoint (not just the signature or another small part of the joinpoint) at the beginning of your advice, at least during development.如果您养成在建议开始时(至少在开发期间)始终打印完整连接点(不仅仅是签名或连接点的另一小部分)的习惯,您自己很容易发现。 You can comment it out later.您可以稍后将其注释掉。 So you can just add所以你可以添加

System.out.println(proceedingJoinPoint);

and you will see what I mean.你会明白我的意思。

The easiest way to fix the problem is to limit the pointcut to either calls or executions.解决问题的最简单方法是将切入点限制为调用或执行。 I suggest the latter if you have a choice, because it is better to just weave one method instead of 100 callers.如果你有选择,我建议后者,因为最好只编织一个方法而不是 100 个调用者。 You want to modify your pointcut to (untested, I am writing "hands-free" on the road)您想将切入点修改为(未经测试,我在路上写“免提”)

@Around("@annotation(main.Retry) && execution(* *(..))")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM