Java重试机制修改

最近无意间看到了一段代码,实话实说看的我有点难受,刚开始的时候还略微有点懵,只是感觉代码很长。等我捋了一遍之后,发现是一段调用远程接口,失败进行重试功能的代码。代码如下:

image.png

方法用到了递归,在重试次数小于零跳出。
说一下存在的问题吧:

  • 接口重试和业务本身不发生关系,所以具有很高的耦合性
  • 方法采用递归实现,有栈溢出的风险
  • 重试逻辑无法进行重用
  • 可配置性比较低

看下怎么改一下:

-抽离出重试代码,预留接口,业务代码填入,抽离工具类如下:

public abstract class MyRetryTemplate<T> {
    //重试次数
    private int retryTime;
    //重试时间
    private int sleepTime;
    //是否倍数增长
    private  boolean multiple = false;

    /**
     * 执行业务方法逻辑,由实现类实现
     *
     * @return
     */
    public abstract T remote() throws Exception;

    public T execute() throws InterruptedException {
        for (int i = 1; i < retryTime + 1; i++) {
            try {
                return remote();
            } catch (Exception e) {
                System.out.println(e.getMessage());
                if (multiple){
                    Thread.sleep(sleepTime);
                }
                else{
                    Thread.sleep(sleepTime * (i));
                }
            }
        }
        return null;
    }

    public T submit(ExecutorService executorService) {
        Future submit = executorService.submit((Callable) () -> execute());
        try {
            return (T) submit.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } 
        return null;
    }

    public MyRetryTemplate setRetryTime(int retryTime) {
        this.retryTime = retryTime;
        return this;
    }

    public MyRetryTemplate setSleepTime(int sleepTime) {
        this.sleepTime = sleepTime;
        return this;
    }

    public MyRetryTemplate setMultiple(boolean multiple) {
        this.multiple = multiple;
        return this;
    }
}

上面的类中,值定义了重试的次数,间隔的时间,和时间的增长参数,预留了remote()抽象方法,交由具体的实现类来实现。类中使用了泛型,支持返回不同的对象。并且支持同步和异步调用。

看下修改后的代码,如下:

image.png

是不是感觉一下清爽了很多,这里重试相关的参数,我直接写死在了代码中,可以通过配置文件和数据库配置引入。这个方法应该还能精简,最后两句感觉还是有点多余,由于不知道是干啥的, 就暂且留在这吧。

修改后的代码,虽然解决了一些上面的问题,但是并没有完全解决,代码的侵入性,上面已经说了既然这是重试的逻辑,就不应该出现在代码中。有没有解决的办法呢,有,切面。

下面看下通过切面该怎么实现。

首先定义一个注解:

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {
    int count() default 0 ;
    long sleep() default 0 ;
}

定义切面

@Aspect
@Component
public class RetryAspect {
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    @Around(value = "@annotation(Retry)")
    public Object execute(ProceedingJoinPoint point, Retry retry) throws InterruptedException {
        System.out.println("----------------- Aspect ---------------------");
        MyRetryTemplate myRetryTemplate = new MyRetryTemplate() {
            @Override
            public ParametersHolder remote() throws Throwable {
                return (ParametersHolder) point.proceed();
            }
        }.setRetryTime(3).setSleepTime(10000).submit(executorService);
        return submit;
    }
}

最终实现:

image.png

在注解中,添加自定义的参数,便可以实现零侵入,也更容易实现方法的复用,如果有其他的业务需要实现重试,直接在业务方法上添加注解即可。

如果不想用这种方法,也可以借助第三方工具guava-retrying和 spring-retry 来实现此功能。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容