欢迎访问察北家纺网

依赖服务或组无法启动(win7网络红叉,无法上网)

频道:百科问答 日期: 浏览:1231

手动重试:使用 while 语句进行重试:

运行上述代码:

上述代码看上去可以解决重试问题,但实际上存在一些弊端:

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

上面的处理方式由于需要对业务代码进行大量修改,虽然实现了功能,但是对原有代码的侵入性太强,可维护性差。所以需要使用一种更优雅一点的方式,不直接修改业务代码,那要怎么做呢?

其实很简单,直接在业务代码的外面再包一层就行了,代理模式在这里就有用武之地了。

这样,重试逻辑就都由代理类来完成,原业务类的逻辑就不需要修改了,以后想修改重试逻辑也只需要修改这个类就行了。

代理模式虽然要更加优雅,但是如果依赖的服务很多的时候,要为每个服务都创建一个代理类,显然过于麻烦,而且其实重试的逻辑都大同小异,无非就是重试的次数和延时不一样而已。如果每个类都写这么一长串类似的代码,显然,不优雅!

另外,如果你近期准备面试跳槽,建议在 Java面试库 小程序在线刷题,涵盖 2000+ 道 Java 面试题,几乎覆盖了所有主流技术面试题。

这时候,动态代理就闪亮登场了。只需要写一个代理处理类就 ok 了

测试:

动态代理可以将重试逻辑都放到一块,显然比直接使用代理类要方便很多,也更加优雅。

这里使用的是JDK动态代理,因此就存在一个天然的缺陷,如果想要被代理的类,没有实现任何接口,那么就无法为其创建代理对象,这种方式就行不通了

既然已经说到了 JDK 动态代理,那就不得不提 CGLib 动态代理了。更多设计模式教程分享给你:23 种设计模式实战(很全)

使用 JDK 动态代理对被代理的类有要求,不是所有的类都能被代理,而 CGLib 动态代理则刚好解决了这个问题

测试:

这样就很棒了,完美的解决了 JDK 动态代理带来的缺陷。优雅指数上涨了不少。

但这个方案仍旧存在一个问题,那就是需要对原来的逻辑进行侵入式修改,在每个被代理实例被调用的地方都需要进行调整,这样仍然会对原有代码带来较多修改。

考虑到以后可能会有很多的方法也需要重试功能,咱们可以将重试这个共性功能通过 AOP 来实现,使用 AOP 来为目标调用设置切面,即可在目标方法调用前后添加一些重试的逻辑

自定义注解:

给需要重试的方法添加注解 @MyRetryable

这样即不用编写重复代码,实现上也比较优雅了:一个注解就实现重试。

Spring Boot 基础就不介绍了,推荐看这个实战项目:

https://github.com/javastacks/spring-boot-best-practice

开启重试功能:在启动类或者配置类上添加 @EnableRetry 注解

在需要重试的方法上添加 @Retryable 注解

该方法调用后会进行重试,最大重试次数为 3,第一次重试间隔为 2s,之后以 2 倍大小进行递增,第二次重试间隔为 4 s,第三次为 8s。

另外,如果你近期准备面试跳槽,建议在 Java面试库 小程序在线刷题,涵盖 2000+ 道 Java 面试题,几乎覆盖了所有主流技术面试题。

Spring 的重试机制还支持很多很有用的特性,由三个注解完成:

查看 @Retryable 注解源码:指定异常重试、次数

@Backoff 注解: 指定重试回退策略(如果因为网络波动导致调用失败,立即重试可能还是会失败,最优选择是等待一小会儿再重试。决定等待多久之后再重试的方法。通俗的说,就是每次重试是立即重试还是等待一段时间后重试)

@Recover 注解: 进行善后工作:当重试达到指定次数之后,会调用指定的方法来进行日志记录等操作

这里还需要再提醒的一点是,由于 Spring Retry 用到了 Aspect 增强,所以就会有使用 Aspect 不可避免的坑——方法内部调用,如果被 @Retryable 注解的方法的调用方和被调用方处于同一个类中,那么重试将会失效

通过以上几个简单的配置,可以看到 Spring Retry 重试机制考虑的比较完善,比自己写AOP实现要强大很多

但也还是存在一定的不足,Spring的重试机制只支持对 异常 进行捕获,而无法对返回值进行校验

因此就算在方法上添加 @Retryable ,也无法实现失败重试

除了使用注解外,Spring Retry 也支持直接在调用时使用代码进行重试:

此时唯一的好处是可以设置多种重试策略:

和 Spring Retry 相比,Guava Retry 具有更强的灵活性,并且能够根据 返回值 来判断是否需要重试

先创建一个Retryer实例,然后使用这个实例对需要重试的方法进行调用,可以通过很多方法来设置重试机制:

还有五个以 withXxx 开头的方法,用来对重试策略/等待策略/阻塞策略/单次任务执行时间限制/自定义监听器进行设置,以实现更加强大的异常处理:

从手动重试,到使用 Spring AOP 自己动手实现,再到站在巨人肩上使用特别优秀的开源实现 Spring Retry 和 Google guava-retrying,经过对各种重试实现方式的介绍,可以看到以上几种方式基本上已经满足大部分场景的需要: