classify
在spring-retry-××.jar的源碼中,我們發(fā)現(xiàn)這個包里面還有一個和retry同級的classify包,顯然它應(yīng)該是retry需要用到,但是又不是包含的retry模型里面的東西。

classify.png
classify包作為retry的輔助類,主要應(yīng)用于RetryPolicy的canRetry()方法中,通過比較捕獲的異常與定義的異常直接關(guān)系,決定是否符合重試條件,其包結(jié)構(gòu)類圖如下:

Classifier.png
- Classifier<C, T> 接口:
是整個包的核心接口,定義了
T classify(C classifiable);
把一個C類型對象,轉(zhuǎn)換為T類型對象,其中T類型通常是枚舉類型或者布爾類型這種可以直接比較結(jié)果的。
- ClassifierSupport<C, T> 類:
一個基礎(chǔ)實現(xiàn),引入默認(rèn)值機制,無論要傳入任何C類型對象,都返回默認(rèn)的T類型對象。 - ClassifierAdapter<C, T> 類:
定義了兩種方式的轉(zhuǎn)換,一種直接Classifier,在需要轉(zhuǎn)換時候調(diào)用,
一種傳入通過識別一個目標(biāo)類中@Classifier注解的方法,把它作為轉(zhuǎn)換的實現(xiàn)類,在需要轉(zhuǎn)換時候調(diào)用。 - SubclassClassifier<T, C>類:
首先要注意這里T和C對調(diào)寫了,實現(xiàn)了能識別一個類和其子類都能被識別到,轉(zhuǎn)換為目標(biāo)類型對象的機制。這對于retry需要的異常類的轉(zhuǎn)換十分重要,通常我們只需要定義某一類的異常重試策略,那么其子類異常也會同樣應(yīng)用到該策略,比如我們定義了數(shù)據(jù)庫錯誤SQLException需要重試,實際運行可能拋出的是SQLTimeoutException,或者BatchUpdateException,它們就都會被捕獲重試。 - BinaryExceptionClassifier類:
明確化了SubclassClassifier<T, C>的類型,其classify()方法把Throwable轉(zhuǎn)換為Boolean。代碼如下:
@Override
public Boolean classify(Throwable classifiable) {
Boolean classified = super.classify(classifiable);
if (!this.traverseCauses) {
return classified;
}
/*
* If the result is the default, we need to find out if it was by default
* or so configured; if default, try the cause(es).
*/
if (classified.equals(this.getDefault())) {
Throwable cause = classifiable;
do {
if (this.getClassified().containsKey(cause.getClass())) {
return classified; // non-default classification
}
cause = cause.getCause();
classified = super.classify(cause);
}
while (cause != null && classified.equals(this.getDefault()));
}
return classified;
}
如果traverseCauses為false,就簡單調(diào)用父類進(jìn)行轉(zhuǎn)換即可,如果為真,就必須一直找Throwable的Cause鏈條,直到找到匹配的轉(zhuǎn)換。
P.S. Traverse: 穿過、橫貫
- PatternMatcher和PatternMatchingClassifier<T> :
能夠把符合樣式的字符串轉(zhuǎn)換為T對象的轉(zhuǎn)換器。
其核心方法為imatch(),對?和*進(jìn)行了處理判斷,判斷輸入的str是否符合某種樣式pattern。 - BackToBackPatternClassifier<C, T> 類:
背對背映射組合,先吧C對象轉(zhuǎn)換為string,然后再把string轉(zhuǎn)換為T對象。
retry頂級接口
retry頂級接口定義了核心的概念,其相互關(guān)系如下:

retry.png
具體含義:請移步spring-retry(1.概念和基本用法),這里簡要分析一些接口方法。
- RetryContext接口:
從圖上可以看到,重試上下文處于核心位置,作為核心數(shù)據(jù)接口,儲存了重試所需要的各類信息。
RetryContext getParent();
從獲取父上下文方法可知,它是一個鏈?zhǔn)浇Y(jié)構(gòu)。
- RetryPolicy接口:
//判斷一個上下文能否重試
boolean canRetry(RetryContext context);
//開啟一個重試上下文環(huán)境
RetryContext open(RetryContext parent);
//關(guān)閉一個重試上下文環(huán)境
void close(RetryContext context);
//出現(xiàn)異常時候,把異常登記到上下文中
void registerThrowable(RetryContext context, Throwable throwable);
從接口參數(shù)可以看出,策略都是根據(jù)上下文情況進(jìn)行判斷分析的。
- RetryOperations接口:
各種花式execute(),根據(jù)可配置的重試行為,進(jìn)行方法的執(zhí)行,其具體的實現(xiàn)就是核心類RetryTemplate - RetryListener接口:
作為重試動作的監(jiān)聽器,給spring-retry加點料,用在統(tǒng)計機制上。監(jiān)聽3類動作:open()在開啟操作之前,close()在關(guān)閉操作之后,onError()在出現(xiàn)錯誤時。 - RetryStatistics接口:
記錄重試統(tǒng)計信息的接口。登記完成數(shù)、開始數(shù)、錯誤數(shù)、中止數(shù)、恢復(fù)數(shù)。 - RetryException及ExhaustedRetryException,TerminatedRetryException異常
定義了retry項目內(nèi)部可能拋出的異常,RetryException是基類。
Exhausted:精疲力竭的
Terminated:終止的
retry.backoff 包
該包定義了當(dāng)出現(xiàn)異常,而又會重試的情況下的補償機制(通常就是延時)。

BackOff.png
- BackOffPolicy接口:
該包的核心接口,包含兩個方法,意識生成一個當(dāng)前補償上下文環(huán)境,二是進(jìn)行補償動作。
//根據(jù)重試上下文生成一個補償上下文
BackOffContext start(RetryContext context);
//根據(jù)補償上下文執(zhí)行延遲操作,可能拋出中斷異常
void backOff(BackOffContext backOffContext) throws BackOffInterruptedException;
- Sleeper接口與ThreadWaitSleeper類:
真正的補償動作具體執(zhí)行器, ThreadWaitSleeper就是調(diào)用了Thread.sleep()方法進(jìn)行延遲。 - StatelessBackOffPolicy抽象類:
其start方法返回null,也就是沒有重試上下文,執(zhí)行backOff時候調(diào)用的是無參數(shù)的doBackOff()。換句話說,代表具體補償動作是固定的,并不依賴上下文環(huán)境。 - NoBackOffPolicy類:
最簡單的默認(rèn)策略,具體延遲為空操作,也就是不補償,不延遲。 - SleepingBackOffPolicy接口:
有一個withSleeper()方法,傳入一個Sleeper。 - UniformRandomBackOffPolicy類:
標(biāo)準(zhǔn)的隨機延遲策略,給定最小值,最大值(默認(rèn)為500L,1500L),會在這個區(qū)間里面隨機進(jìn)行補償延遲。
7 FixedBackOffPolicy類:
標(biāo)準(zhǔn)的固定延遲策略,每次延遲固定時間(默認(rèn)1000L) - ExponentialBackOffPolicy類和ExponentialRandomBackOffPolicy:
這兩個類都是SleepingBackOffPolicy的實現(xiàn),內(nèi)部用ThreadWaitSleeper延遲。實現(xiàn)的是延遲指數(shù)倍增的效果,區(qū)別是ExponentialBackOffPolicy是固定倍增,ExponentialRandomBackOffPolicy加入了隨機性。
例如:
* {@link ExponentialBackOffPolicy} 延遲序列為: [50, 100, 200, 400, 800]
*
* {@link ExponentialRandomBackOffPolicy} 延遲序列可能為: [76, 151, 304, 580, 901] 或者 [53, 190,
* 267, 451, 815]
retry.context 包
該包只有一個類RetryContextSupport,重試上下文的具體實現(xiàn)。
- 擴展AttributeAccessorSupport:內(nèi)部有個linkedHashMap存儲標(biāo)準(zhǔn)屬性外的其他屬性
- 有parent屬性,在構(gòu)造時候傳入其父上下文,這樣就維護(hù)了一個鏈表信息,方便后續(xù)查找。
- count和lastException是記錄型屬性,登記這個上下文的狀態(tài)。