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

image.png

方法用到了递归,在重试次数小于零跳出。

说一下存在的问题吧:

接口重试和业务本身不发生关系,所以具有很高的耦合性

方法采用递归实现,有栈溢出的风险

重试逻辑无法进行重用

可配置性比较低

看下怎么改一下:

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

public abstract class MyRetryTemplate {

//重试次数

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 来实现此功能。

java 重试_Java重试机制修改相关推荐

  1. java 反射 修改字段_Java反射机制-修改字段值

    需要用到的类: Field 需要用到的方法: getDeclaredField(); getField(); setAccessible(); 需要用到的字段: public int a=5; pub ...

  2. java内省_java内省机制

    一.内省是什么.实现方式: 内省(Introspector)是Java语言对Bean类属性.事件的一种缺省处理方法. 例如类A中有属性name,那我们可以通过getName,setName来得到其值或 ...

  3. java万法_Java内省机制和 BeanUtils实现

    内省(Introspector) Java 语言对 Bean 类属性.事件的一种缺省处理方法. 例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的 ...

  4. java 可见_Java可见性机制的原理

    基本概念 1.可见性 当一个线程修改了共享变量时,另一个线程可以读取到这个修改后的值. 2.内存屏障(Memory Barriers) 处理器的一组指令,用于实现对内存操作的顺序限制. 3.缓冲行 C ...

  5. foxmail邮件加载失败重试_java retry(重试) spring retry, guava retrying 详解

    系列说明 java retry 的一步步实现机制. java-retry 源码地址 情景导入 简单的需求 产品经理:实现一个按条件,查询用户信息的服务. 小明:好的.没问题. 代码 UserServi ...

  6. java 深拷贝_java 深拷贝与浅拷贝机制详解

    java 深拷贝与浅拷贝机制详解 概要: 在Java中,拷贝分为深拷贝和浅拷贝两种.java在公共超类Object中实现了一种叫做clone的方法,这种方法clone出来的新对象为浅拷贝,而通过自己定 ...

  7. java f反射_java反射机制

    反射定义 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...

  8. java反射机制详解_JAVA反射机制详解_JSP/Java编程_互联网开发技术网_传播最新的编程技术_php361.com...

    今天,下午在和朋友聊天的时候,聊起了反射这个话题. 我们就从下面这个段简单的代码开始吧. 这个代码输出什么,想必大部分的读者跟我一样,会很快地知道答案:0 1 2 3 4 5 6 7 8 9.事实也是 ...

  9. java异常处理代码详解_Java异常处理机制总结

    概念介绍 异常是发生在程序执行过程中阻碍程序正常执行的错误事件,当一个程序出现错误时,可能的情况有如下3种: 语法错误 代码的格式错了,某个字母输错了 运行时错误 空指针异常,数组越界,除数为零等 逻 ...

最新文章

  1. 转:MySQL 开发实践 8 问,你能 hold 住几个?
  2. java classname.this_java 中 类名.this与类名.class
  3. 我们应该使用什么指标来描述数据中心及其效率?
  4. (转)iOS 6的Rotation--详细版本
  5. Java——集合转数组并对其进行遍历
  6. python doc_2019-2020年Python3中文教程完整版.doc
  7. 两个电脑如何切换以方便使用文件
  8. Android Jetpack 之 ViewModel
  9. 如何把电脑文件传到虚拟机
  10. 3842开关电源完整原理图_8大常见开关电源电路分析,让你项目设计更轻松!
  11. Docker到底是什么?为什么它这么火!
  12. 软件GUI测试中的关注点
  13. Improving Opencv10 More Morphology Transformations
  14. 一款云迁移产品的成长史
  15. VS2013 安装及问题解决
  16. lcx的使用-内网穿透
  17. 搜狗输入法安装上问题
  18. 计算机网络基础——CS架构与BS架构、OSI七层协议、tcp/ip五层模型讲解
  19. 22 个最常用的 Python 包
  20. Git 中 cat 的使用

热门文章

  1. RxJava 2.0的基本使用
  2. 你真正的去了解过Linux吗?不单单是一些命令操作,比如它的系统架构!!!
  3. java线程----生产者和消费者问题
  4. 数据结构: 试用判定树的方法给出在中序线索化二叉树上: (1) 如何搜索指定结点的在中序下的后继。 (2) 如何搜索指定结点的在前序下的后继。(3) 如何搜索指定结点的在后序下的后继。
  5. 【Docker】Docker操作常用命令
  6. 【JavaWeb】Response请求转发与重定向辨析
  7. 【计组实验】P3 Verilog多周期处理器开发 MIPS指令集
  8. JDK 14的新特性:instanceof模式匹配
  9. Redis学习之Sentinel(四)
  10. JUC锁-Semaphore(八)