簡體   English   中英

如何使用 AspectJ 在 java 中實現重試機制

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

我正在嘗試使用AspectJ實現重試機制。 如果方法拋出任何異常, AspectJ應該再次調用方法。

這是我的代碼:

重試注釋:

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

重試方面:

@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;
    }
}

主要方法:

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");
    }
}

如果我的理解是正確的,程序應該打印兩次“方法 1”並拋出異常。但是“方法 1”被打印了 4 次。 這是 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)

請提及我的實施是否有任何問題。

您使用 AspectJ,而不是 Spring AOP,這就是為什么您的切入點同時匹配

  • call() (方法調用的來源)和
  • execution() (目標方法本身)

連接點,因此您會看到 4 個而不是 2 個日志輸出。 如果您養成在建議開始時(至少在開發期間)始終打印完整連接點(不僅僅是簽名或連接點的另一小部分)的習慣,您自己很容易發現。 您可以稍后將其注釋掉。 所以你可以添加

System.out.println(proceedingJoinPoint);

你會明白我的意思。

解決問題的最簡單方法是將切入點限制為調用或執行。 如果你有選擇,我建議后者,因為最好只編織一個方法而不是 100 個調用者。 您想將切入點修改為(未經測試,我在路上寫“免提”)

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM