扒一扒@Retryable注解,很优雅,有点意思! (4)

简介: 扒一扒@Retryable注解,很优雅,有点意思! (4)

Recover逻辑


首先要说明的是 @Recover 注解并不是一个必须要有的东西,前面我们也分析了,就不再赘述。

但是这个功能用起来确实是不错的,绝大部分异常都应该有对应的兜底措施。

这个东西,就是来执行兜底的动作的。

它的源码也非常容易找到,就紧跟在重试逻辑之后:

image.png

下 Debug 几步你就会走到这个地方来:

org.springframework.retry.annotation.RecoverAnnotationRecoveryHandler#recover


image.png

又是一个反射调用,这里的 method 已经是 channelNotResp 方法了。

那么问题就来了:Spring-retry 是怎么知道我的重试方法就是 channelNotResp 的呢?

仔细看上面的截图中的 method 对象,不难发现它是方法的第一行代码产生的:

Method method = findClosestMatch(args, cause.getClass());

这个方法从名字和返回值上看叫做找一个最相近的方法。但是具体不太明白啥意思。

跟进去看一眼它在干啥:

image.png

image.png

这个 Map 里面的 channelNotResp 是什么时候放进去的呢?

很简单,看一下这个 Map 的 put 方法调用的地方就完事了:

image.png

就这两个 put 的地方,源码位于下面这个方法中:

org.springframework.retry.annotation.RecoverAnnotationRecoveryHandler#init

从截图中可以看出,这里是在找 class 里面有没有被 @Recover 注解修饰的方法。

我在第 172 行打上断点,调试一下看一下具体的信息,你就知道这里是在干什么了。

image.png

在你发起调用之后,程序会在断点处停下,至于是怎么走到这里的,前面说过,看调用堆栈,就不再赘述了。

关于这个 doWith 方法,我们把调用堆栈往上看一步,就知道这里是在解析我们的 RetryService 类里面的所有方法:

image.png

当解析到 channelNotResp 方法的时候,会识别出该方法上标注了 @Recover 注解。

但从源码上看,要进行进一步解析,要满足 if 条件。而 if 条件除了要有 Recover 之外,还需要满足这个东西:

method.getReturnType().isAssignableFrom(failingMethod.getReturnType())

isAssignableFrom 方法是判断是否为某个类的父类。

就是的 method 和 failingMethod 分别如下:


image.png

这是在检查被 @Retryable 标注的方法和被 @Recover 标注的方法的返回值是否匹配,只有返回值匹配才说明这是一对,应该进行解析。

比如,我把源码改成这样:

image.png

当它解析到 channelNotRespStr 方法的时候,会发现虽然被 @Recover 注解修饰了,但是返回值并不一致,从而知道它并不是目标方法 callChannel 的兜底方法。

源码里面的常规套路罢了。

再加入一个 callChannelSrt 方法,在上面的源码中 Spring-retry 就能帮你解析出谁和谁是一对:

image.png

接着看一下如果满足条件,匹配上了,if 里面在干啥呢?

image.png

这是在获取方法上的入参呀,但是仔细一看,也只是为了获取第一个参数,且这个参数要满足一个条件:

Throwable.class.isAssignableFrom(parameterTypes[0])

必须是 Throwable 的子类,也就说说它必须是一个异常。用 type 字段来承接,然后下面会把它给存起来。

第一次看的时候肯定没看懂这是在干啥,没关系,我看了几次看明白了,给你分享一下,这里是为了这一小节最开始出现的这个方法服务的:

image.png

在这里面获取了这个 type,判断如果 type 为 null 则默认为 Throwable.class。

如果有值,就判断这里的 type 是不是当前程序抛出的这个 cause 的同类或者父类。

再强调一遍,从这个方法从名字和返回值上看,我们知道是要找一个最相近的方法,前面我说具体不太明白啥意思都是为了给你铺垫了一大堆 methods 这个 Map 是怎么来的。

其实我心里明镜儿似的,早就想扯下它的面纱了。

image.png

来,跟着我的思路马上就能看到葫芦里到底卖的是什么酒了。

你想,findClosestMatch,这个 Closest 是 Close 的最高级,表示最接近的意思。

既然有最接近,那么肯定是有几个东西放在一起,这里面只有一个是最符合要求的。

在源码中,这个要求就是“cause”,就是当前抛出的异常。

而“几个东西”指的就是这个 methods 装的东西里面的 type 属性。

还是有点晕,对不对,别慌,下面这张图片一出来,马上就不晕了:

image.png

目录
相关文章
|
存储 算法 C++
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
1405 1
|
3月前
|
Java 测试技术 数据库
使用Spring的@Retryable注解进行自动重试
在现代软件开发中,容错性和弹性至关重要。Spring框架提供的`@Retryable`注解为处理瞬时故障提供了一种声明式、可配置的重试机制,使开发者能够以简洁的方式增强应用的自我恢复能力。本文深入解析了`@Retryable`的使用方法及其参数配置,并结合`@Recover`实现失败回退策略,帮助构建更健壮、可靠的应用程序。
456 1
使用Spring的@Retryable注解进行自动重试
|
12月前
|
IDE iOS开发 Python
小白如何开始使用通义灵码(含安装IDE、安装灵码插件)
PyCharm 和 IntelliJ IDEA 下载安装及通义灵码插件下载安装说明
10445 9
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
305 4
|
JavaScript 前端开发 API
javaScript中常用的String方法以及注意点总结
本文总结了JavaScript中常用的String对象的方法及其注意事项,包括大小写转换、字符获取、子字符串截取、字符串拼接、去除空格、替换、分割以及查找字符串中字符的索引等操作。提供了每种方法的使用示例代码,帮助理解它们的具体用法和差异。
232 2
|
前端开发 Java API
Swagger接口文档 —— 手把手教学,全方位超详细小白能看懂,百分百能用Java版
本文提供了一份详细的Swagger接口文档生成工具的使用教程,包括了导入依赖、配置类设置、资源映射、拦截器配置、Swagger注解使用、生成接口文档、在线调试页面访问以及如何设置全局参数(如token),旨在帮助Java开发者快速上手Swagger。
9104 0
Swagger接口文档 —— 手把手教学,全方位超详细小白能看懂,百分百能用Java版
|
开发框架 前端开发 JavaScript
循序渐进VUE+Element 前端应用开发(10)--- 基于vue-echarts处理各种图表展示
循序渐进VUE+Element 前端应用开发(10)--- 基于vue-echarts处理各种图表展示
|
编解码 安全 Ubuntu
Android Selinux 问题处理笔记
这篇文章是关于处理Android系统中SELinux权限问题的笔记,介绍了如何通过分析SELinux拒绝的日志、修改SELinux策略文件,并重新编译部署来解决权限问题,同时提供了一些SELinux的背景知识和实用工具。
1103 0
|
应用服务中间件 Linux API
Linux 利用 Cloudflare API 配置 acme.sh 自动续签 SSL (Apache、Nginx适用)
安装acme.sh工具,命令为`curl https://get.acme.sh | sh -s email=你的邮箱`。接着配置Cloudflare API,创建并记录API令牌及Zone ID。最后通过`acme.sh --issue -d 你的域名 --dns dns_cf`签发SSL证书,对于Nginx可使用`acme.sh --install-cert`命令安装证书,并设置自动重载Nginx服务。
|
SQL 存储 Java
Hive教程(06)- Hive SerDe序列化与反序列化
Hive教程(06)- Hive SerDe序列化与反序列化
626 0