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

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. c语言delay_C语言编程制作“古怪手电筒”,有光的时候就会亮,没光绝不会亮...
  2. 12C OCP IZO-62 题库(8月以前)
  3. oracle 临时表存在哪里_openGauss魔改PG?它能兼容Oracle的数据库表吗?
  4. 成功解决AttributeError: 'NoneType' object has no attribute '__array_interface__'
  5. JavaScript 总结几个提高性能知识点
  6. python适合什么样的人群_什么样的人比较适合选择Python开发+人工智能技术?
  7. Tensorflow模型加载与保存、Tensorboard简单使用
  8. Oracle 11g 频繁遭遇 CheckPoint incomplete问题分析(直播预告)
  9. C语言栈的面试题,[面试题]EMC易安信-C语言函数堆栈的思考
  10. 深入理解Angular2变化监测和ngZone
  11. 基于openoffice+pdfobject.js实现文档上传以及在线预览功能
  12. 产品读书《自控力:斯坦福大学最受欢迎的心理学课程》
  13. U盘不能复制超过4G的文件解决方法
  14. Slider网站欣赏
  15. 15、react 的 非受控组件 和 受控组件
  16. 两个子组件之间的传值
  17. pytorch repeat 使用详解
  18. python——洗牌算法
  19. 【Python】实现给小仙女定时推送消息
  20. 心跳服务1.0(Heart Rate Service 1.0)

热门文章

  1. 阿里巴巴HBase高可用8年填坑实录
  2. MapReduce 源码分析(一)准备阶段
  3. 经典 MyBatis 面试题
  4. 【MS Word技巧】word如何批量把括号内字体变绿?
  5. 【Java】Java中的异常处理:何时抛出异常,何时捕获异常?
  6. 【PAT甲级 sc.nextInt()的使用】1008 Elevator (20 分) Java版 9/9通过
  7. dart系列之:dart语言中的异常
  8. 突发!HashiCorp禁止在中国使用企业版VAULT软件
  9. nginx tcp代理_nginx——TCP/UDP Load Balancing
  10. deepin如何布署python_【玩转deepin】简单三步,教你在deepin15.11上安装Python3.7.4