兩種通過aop設定重試機制的方式

2021-09-26 07:33:22 字數 3988 閱讀 4513

注意:

1.不要在同乙個類中呼叫自定義的註解,如果controller呼叫,註解要放在service層(其他類)

2.如果有配置aop掃瞄的包,不能只設定掃瞄control下的檔案

方式一:

/**

* controller層

*/ public void test() throws exception

/**

* service層

*/@component

public class demoservice

return a;

}}

/**

* 自定義註解

* * @author leon

* @date 2019/08/19

*/@documented

@target(elementtype.method)

@retention(retentionpolicy.runtime)

public @inte***ce retry

/**

* 模版

* * @author leon

* @date 2019/08/19

*/public abstract class retrytemplate

public retrytemplate setsleeptime(int sleeptime)

this.sleeptime = sleeptime;

return this;

}public int getretrytime()

public retrytemplate setretrytime(int retrytime)

this.retrytime = retrytime;

return this;

}/**

* 留給業務方實現

* 重試的業務執行**

* 失敗時請丟擲乙個異常

** todo 確定返回的封裝類,根據返回結果的狀態來判定是否需要重試

** @return

*/protected abstract object dobiz() throws throwable;

public object execute() throws interruptedexception catch (throwable e) ", e);

thread.sleep(sleeptime);}}

return null;

}public object submit(executorservice executorservice)

return executorservice.submit((callable) () -> execute());

}}

/**

* 切面

* * @author leon

* @date 2019/08/19

*/@aspect

@component

@slf4j

public class retryaspect

};retrytemplate.setretrytime(retry.count())

.setsleeptime((int)retry.sleep());

if (retry.asyn()) else

}}

方法2:

/**

* controller層

** 直接進入切面,再返回到方法

* @throws exception

*/@retrydot(times = 5, waittime = 2 * 1000)

public void aa() throws exception

/**

* 自定義註解

* 《用來異常重試》

* 當這兩個陣列的長度都為0時, 直接執行重試邏輯。

* * @author zmc

* @date 2019/08/19

* @see exceptionretryaspect

*/@documented

@target(elementtype.method)

@retention(retentionpolicy.runtime)

public @inte***ce retrydot ;

/*** 需要捕獲的異常, 如果需要捕獲則捕獲重試。否則丟擲異常

* 執行順序 needthrowexceptions --> catchexceptions 兩者並不相容

* 當 needthrowexceptions 判斷需要丟擲異常時, 丟擲異常, 否則進入此方法, 異常不在此陣列內則丟擲異常

* 當陣列長度為0時, 不會執行捕獲異常的邏輯。

** @return 異常陣列

*/class catchexceptions() default {};

/*** 是否支援非同步重試方式

* @return

*/boolean asyn() default false;

/**

* 切面

* controller(呼叫之後)會直接進入該切面;

* 跑到joinpoint.proceed()才回到業務層

* 捕獲異常之後再回到該切面進行迴圈重試

* * 《異常重試切面》

* * @author leon

* @date 2019/08/19

*/@aspect

@component

public class exceptionretryaspect

@around("retrypointcut()")

public object around(proceedingjoinpoint joinpoint) throws throwable , 方法名稱{}, 方法引數{}", uuid, name, json.tojsonstring(args));

int times = retry.times();

long waittime = retry.waittime();

class needthrowexceptions = retry.needthrowexceptions();

class catchexceptions = retry.catchexceptions();

// check param

if (times <= 0)

for (; times >= 0; times--) catch (exception e) 失敗, 異常在需要丟擲的範圍{}, 業務丟擲的異常型別{}", uuid, needthrowexceptions,

e.getclass().getname());

throw e;}}

}// 如果需要丟擲異常,而且需要捕獲的異常為空那就需要再丟擲

if (catchexceptions.length > 0)

}if (!needcatch) 失敗, 異常不在需要捕獲的範圍內, 需要捕獲的異常{}, 業務丟擲的異常型別{}", uuid, catchexceptions,

e.getclass().getname());

throw e;}}

// 如果接下來沒有重試機會的話,直接報錯

if (times <= 0) 失敗", uuid);

throw e;

}// 休眠 等待下次執行

if (waittime > 0)

logger.warn("執行重試切面{}, 還有{}次重試機會, 異常型別{}, 異常資訊{}, 棧資訊{}", uuid, times, e.getclass().getname(), e.getmessage(), e.getstacktrace());}}

return false;

}}

AOP的兩種實現方式

execution方式 關於環繞通知和前,後通知 切點執行順序介紹 around用proceedingjoinpoint before,after用joinpoint proceedingjoinpoint時joinpoint的子類,額外提供了proceed方法,讓切點繼續執行,然後才可以進行環繞通...

兩種獲取Oracle Sequence的方法

前提 create table booking id integer not null,date made date,reserved until timestamp,price decimal 15,2 not null,purchase id integer,primary key id cre...

兩種禁止USB autosuspend的方法

在有些情況下,由於低功耗情況下,usb硬體的bug或者提高usb resume的速度,我們需要禁止usb的 autosuspend,下面是兩種方法。1 在bootloader的bootargs裡加上 usbcore.autosuspend 1 2 檔案系統起來後,執行如下命令,disable掉run...