欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中的接口重試機制spring-retry之listeners參數(shù)解析

 更新時間:2024年01月24日 08:50:22   作者:北漂碼農(nóng)有話說  
這篇文章主要介紹了Spring中的接口重試機制spring-retry之listeners參數(shù)解析,注解@Retryable有一個參數(shù)listeners沒有說明,那么本篇文章我們詳細介紹一個這個參數(shù)的用,需要的朋友可以參考下

背景

上篇文章中我們簡單介紹了spring-retry的功能及簡單用法,但是注解@Retryable還有一個參數(shù)listeners我們沒有進行說明, 那么本篇文章我們詳細介紹一個這個參數(shù)的用法。

分析

由參數(shù)名字我們我們可以知道,這里面可以配置一些監(jiān)聽器。

那這些監(jiān)聽器該如何進行配置呢?首先我們分析源碼。

注解源碼

我們只保留這個參數(shù)的源碼,其他的省略掉了。

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Retryable {
	/**
	 * Bean names of retry listeners to use instead of default ones defined in Spring
	 * context
	 * @return retry listeners bean names
	 */
	String[] listeners() default {};
}

說明:源碼中該參數(shù)的解釋:使用的重試監(jiān)聽器的Bean名稱,而不是在Spring上下文中定義的默認(rèn)名稱,我們可以大膽的猜測出 這個是一個特定的Bean,需要開發(fā)者自己定義。

并且可以接收的參數(shù)是數(shù)組形式,那么問題是如何定義呢?

處理注解源碼

我們上篇文章中提到,處理注解 @Retryable的類為:AnnotationAwareRetryOperationsInterceptor,那么我們就在這個類中找尋我們要的答案。

方法getListenersBeans() 源碼

private RetryListener[] getListenersBeans(String[] listenersBeanNames) {
    RetryListener[] listeners = new RetryListener[listenersBeanNames.length];
    for (int i = 0; i < listeners.length; i++) {
        listeners[i] = this.beanFactory.getBean(listenersBeanNames[i], RetryListener.class);
    }
    return listeners;
}

有上面的代碼我們可以知道,我們自己定義的監(jiān)聽器肯定和RetryListener有著某種關(guān)系。下面我們分析該類的源碼

RetryListener 源碼

/**
 * Interface for listener that can be used to add behaviour to a retry. Implementations of
 * {@link RetryOperations} can chose to issue callbacks to an interceptor during the retry
 * lifecycle.
 */
public interface RetryListener {
	/**
	 * Called before the first attempt in a retry. For instance, implementers can set up
	 * state that is needed by the policies in the {@link RetryOperations}. The whole
	 * retry can be vetoed by returning false from this method, in which case a
	 * {@link TerminatedRetryException} will be thrown.
	 * @param <T> the type of object returned by the callback
	 * @param <E> the type of exception it declares may be thrown
	 * @param context the current {@link RetryContext}.
	 * @param callback the current {@link RetryCallback}.
	 * @return true if the retry should proceed.
	 */
	<T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback);
	/**
	 * Called after the final attempt (successful or not). Allow the interceptor to clean
	 * up any resource it is holding before control returns to the retry caller.
	 * @param context the current {@link RetryContext}.
	 * @param callback the current {@link RetryCallback}.
	 * @param throwable the last exception that was thrown by the callback.
	 * @param <E> the exception type
	 * @param <T> the return value
	 */
	<T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable);
	/**
	 * Called after every unsuccessful attempt at a retry.
	 * @param context the current {@link RetryContext}.
	 * @param callback the current {@link RetryCallback}.
	 * @param throwable the last exception that was thrown by the callback.
	 * @param <T> the return value
	 * @param <E> the exception to throw
	 */
	<T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable);
}

分析:首先這個是一個接口,那不用想了,開發(fā)者自定義的監(jiān)聽器,必然要實現(xiàn)這個接口。

實現(xiàn)

由于listeners這個參數(shù)可以是多個,并且入?yún)⑹且粋€數(shù)組,我們先來定義兩哥監(jiān)聽器。代碼如下

RetryListenerBean

@Slf4j
public class RetryListenerBean implements RetryListener {

    @Override
    public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
        log.info("執(zhí)行了 open 方法 ");
        return true;
    }

    @Override
    public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        log.info("執(zhí)行了 onError 方法,說明出現(xiàn)了異常");
    }

    @Override
    public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        log.info("執(zhí)行了 close 方法 ");
    }
}

RetryListenerTwoBean

@Slf4j
public class RetryListenerTwoBean implements RetryListener {

    @Override
    public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
        log.info("執(zhí)行了 第二個  open 方法 ");
        return true;
    }

    @Override
    public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        log.info("執(zhí)行了 第二個 onError 方法,說明出現(xiàn)了異常");
    }

    @Override
    public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
        log.info("執(zhí)行了 第二個 close 方法 ");
    }
}

分析1:我們定義了自己的兩個監(jiān)聽器,在參數(shù)listeners進行配置,代碼如下:

@Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5),listeners = {"retryListenerBean", "retryListenerTwoBean"} )

分析2:那么框架是如何識別到我們配置的監(jiān)聽器呢?請看源碼

for (int i = 0; i < listeners.length; i++) {
    listeners[i] = this.beanFactory.getBean(listenersBeanNames[i], RetryListener.class);
}

分析3:在上面的代碼中,我們發(fā)現(xiàn)了beanFactory#getBean(),那么一切真相大白。因此我們必須將自己定義的監(jiān)聽器 交由Spring 進行管理。所以我們需要將自己定義的監(jiān)聽器進行配置。

監(jiān)聽器配置

我們將自己定義的監(jiān)聽器進行配置,由Spring進行管理,配置代碼如下:

@Configuration
public class Config {

    @Bean("retryListenerBean")
    public RetryListenerBean listenerBean(){
        return new RetryListenerBean();
    }

    @Bean("retryListenerTwoBean")
    public RetryListenerTwoBean listenerTwoBean(){
        return new RetryListenerTwoBean();
    }

}

進行如上代碼配置后,就可以通過Bean的名稱通過getBean的方法進行獲取監(jiān)聽器的實例了。

測試

啟動項目,我們使用postman進行測試。

日志如下:

2023-07-23 14:37:07.102  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.controller.RetryController       : Controller 請求入?yún)椋?22
2023-07-23 14:37:25.312  INFO 12932 --- [nio-8111-exec-9] o.t.s.loopretry.bean.RetryListenerBean   : 執(zhí)行了 open 方法 
2023-07-23 14:37:25.313  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.bean.RetryListenerTwoBean        : 執(zhí)行了 第二個  open 方法 
2023-07-23 14:37:30.816  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.service.impl.RetryServiceImpl    : Service 請求入?yún)椋?22
2023-07-23 14:37:31.285  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.service.impl.RetryServiceImpl    : 進入測試方法,目前時間為:Sun Jul 23 14:37:31 CST 2023
2023-07-23 14:37:38.312  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.bean.RetryListenerTwoBean        : 執(zhí)行了 第二個 onError 方法,說明出現(xiàn)了異常
2023-07-23 14:37:38.313  INFO 12932 --- [nio-8111-exec-9] o.t.s.loopretry.bean.RetryListenerBean   : 執(zhí)行了 onError 方法,說明出現(xiàn)了異常
2023-07-23 14:37:54.729  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.service.impl.RetryServiceImpl    : Service 請求入?yún)椋?22
2023-07-23 14:37:54.729  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.service.impl.RetryServiceImpl    : 進入測試方法,目前時間為:Sun Jul 23 14:37:54 CST 2023
2023-07-23 14:37:54.729  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.bean.RetryListenerTwoBean        : 執(zhí)行了 第二個 onError 方法,說明出現(xiàn)了異常
2023-07-23 14:37:54.729  INFO 12932 --- [nio-8111-exec-9] o.t.s.loopretry.bean.RetryListenerBean   : 執(zhí)行了 onError 方法,說明出現(xiàn)了異常
2023-07-23 14:38:02.498  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.service.impl.RetryServiceImpl    : Service 請求入?yún)椋?22
2023-07-23 14:38:02.499  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.service.impl.RetryServiceImpl    : 進入測試方法,目前時間為:Sun Jul 23 14:38:02 CST 2023
2023-07-23 14:38:02.499  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.bean.RetryListenerTwoBean        : 執(zhí)行了 第二個 onError 方法,說明出現(xiàn)了異常
2023-07-23 14:38:02.499  INFO 12932 --- [nio-8111-exec-9] o.t.s.loopretry.bean.RetryListenerBean   : 執(zhí)行了 onError 方法,說明出現(xiàn)了異常
2023-07-23 14:38:02.500  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.service.impl.RetryServiceImpl    : 異常出現(xiàn)后的回調(diào)操作,入?yún)椋?22,當(dāng)前時間為:Sun Jul 23 14:38:02 CST 2023
2023-07-23 14:38:02.501  INFO 12932 --- [nio-8111-exec-9] o.t.s.l.bean.RetryListenerTwoBean        : 執(zhí)行了 第二個 close 方法 
2023-07-23 14:38:02.502  INFO 12932 --- [nio-8111-exec-9] o.t.s.loopretry.bean.RetryListenerBean   : 執(zhí)行了 close 方法 

以上的日志,可以看出來我們定義的監(jiān)聽器中的日志輸出,監(jiān)聽器的邏輯進行了執(zhí)行。

小結(jié)

由監(jiān)聽器的代碼,其中包括三個方案open、onError和close我們結(jié)合日志的輸出順序。

首先在執(zhí)行我們的業(yè)務(wù)邏輯之前,先執(zhí)行 open方案,相當(dāng)于一個前置攔截器,我們可以在這個方法中實現(xiàn)一些前置的邏輯操作。

遇到異常的情況會執(zhí)行onError方法。最終會 執(zhí)行close方法。因此我們在不同的階段利用這三個方法可以實現(xiàn)我們的想要的業(yè)務(wù)邏輯。

到此這篇關(guān)于Spring中的接口重試機制spring-retry之listeners參數(shù)解析的文章就介紹到這了,更多相關(guān)spring-retry之listeners參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論