注意:
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...