简体   繁体   中英

How to implement Retry mechanism in java using AspectJ

I am trying to implement Retry mechanism using AspectJ . If a method throws any exception AspectJ should invoke method once again.

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. Here is 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

  • call() (the source of the method call) and
  • execution() (the target method itself)

joinpoints, thus you see 4 instead of 2 log outputs. 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. You want to modify your pointcut to (untested, I am writing "hands-free" on the road)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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