spring-retry(2.源码查看classify包,retry接口、backoff 包)


classify

在spring-retry-××.jar的源码中,我们发现这个包里面还有一个和retry同级的classify包,显然它应该是retry需要用到,但是又不是包含的retry模型里面的东西。

classify.png

classify包作为retry的辅助类,主要应用于RetryPolicy的canRetry()方法中,通过比较捕获的异常与定义的异常直接关系,决定是否符合重试条件,其包结构类图如下:


Classifier.png
  1. Classifier<C, T> 接口:
    是整个包的核心接口,定义了
T classify(C classifiable);

把一个C类型对象,转换为T类型对象,其中T类型通常是枚举类型或者布尔类型这种可以直接比较结果的。

  1. ClassifierSupport<C, T> 类:
    一个基础实现,引入默认值机制,无论要传入任何C类型对象,都返回默认的T类型对象。
  2. ClassifierAdapter<C, T> 类:
    定义了两种方式的转换,一种直接Classifier,在需要转换时候调用,
    一种传入通过识别一个目标类中@Classifier注解的方法,把它作为转换的实现类,在需要转换时候调用。
  3. SubclassClassifier<T, C>类:
    首先要注意这里T和C对调写了,实现了能识别一个类和其子类都能被识别到,转换为目标类型对象的机制。这对于retry需要的异常类的转换十分重要,通常我们只需要定义某一类的异常重试策略,那么其子类异常也会同样应用到该策略,比如我们定义了数据库错误SQLException需要重试,实际运行可能抛出的是SQLTimeoutException,或者BatchUpdateException,它们就都会被捕获重试。
  4. BinaryExceptionClassifier类:
    明确化了SubclassClassifier<T, C>的类型,其classify()方法把Throwable转换为Boolean。代码如下:
@Override
    public Boolean classify(Throwable classifiable) {
        Boolean classified = super.classify(classifiable);
        if (!this.traverseCauses) {
            return classified;
        }

        /*
         * If the result is the default, we need to find out if it was by default
         * or so configured; if default, try the cause(es).
         */
        if (classified.equals(this.getDefault())) {
            Throwable cause = classifiable;
            do {
                if (this.getClassified().containsKey(cause.getClass())) {
                    return classified; // non-default classification
                }
                cause = cause.getCause();
                classified = super.classify(cause);
            }
            while (cause != null && classified.equals(this.getDefault()));
        }

        return classified;
    }

如果traverseCauses为false,就简单调用父类进行转换即可,如果为真,就必须一直找Throwable的Cause链条,直到找到匹配的转换。
P.S. Traverse: 穿过、横贯

  1. PatternMatcher和PatternMatchingClassifier<T> :
    能够把符合样式的字符串转换为T对象的转换器。
    其核心方法为imatch(),对?和*进行了处理判断,判断输入的str是否符合某种样式pattern。
  2. BackToBackPatternClassifier<C, T> 类:
    背对背映射组合,先吧C对象转换为string,然后再把string转换为T对象。

retry顶级接口

retry顶级接口定义了核心的概念,其相互关系如下:
retry.png

具体含义:请移步spring-retry(1.概念和基本用法),这里简要分析一些接口方法。

  1. RetryContext接口:
    从图上可以看到,重试上下文处于核心位置,作为核心数据接口,储存了重试所需要的各类信息。
RetryContext getParent();
从获取父上下文方法可知,它是一个链式结构。
  1. RetryPolicy接口:
    //判断一个上下文能否重试
    boolean canRetry(RetryContext context);
    //开启一个重试上下文环境
    RetryContext open(RetryContext parent);
    //关闭一个重试上下文环境
    void close(RetryContext context);
    //出现异常时候,把异常登记到上下文中
    void registerThrowable(RetryContext context, Throwable throwable);

从接口参数可以看出,策略都是根据上下文情况进行判断分析的。

  1. RetryOperations接口:
    各种花式execute(),根据可配置的重试行为,进行方法的执行,其具体的实现就是核心类RetryTemplate
  2. RetryListener接口:
    作为重试动作的监听器,给spring-retry加点料,用在统计机制上。监听3类动作:open()在开启操作之前,close()在关闭操作之后,onError()在出现错误时。
  3. RetryStatistics接口:
    记录重试统计信息的接口。登记完成数、开始数、错误数、中止数、恢复数。
  4. RetryException及ExhaustedRetryException,TerminatedRetryException异常
    定义了retry项目内部可能抛出的异常,RetryException是基类。
    Exhausted:精疲力竭的
    Terminated:终止的

retry.backoff 包

该包定义了当出现异常,而又会重试的情况下的补偿机制(通常就是延时)。
BackOff.png
  1. BackOffPolicy接口:
    该包的核心接口,包含两个方法,意识生成一个当前补偿上下文环境,二是进行补偿动作。
    //根据重试上下文生成一个补偿上下文
    BackOffContext start(RetryContext context);
    //根据补偿上下文执行延迟操作,可能抛出中断异常
    void backOff(BackOffContext backOffContext) throws BackOffInterruptedException;
  1. Sleeper接口与ThreadWaitSleeper类:
    真正的补偿动作具体执行器, ThreadWaitSleeper就是调用了Thread.sleep()方法进行延迟。
  2. StatelessBackOffPolicy抽象类:
    其start方法返回null,也就是没有重试上下文,执行backOff时候调用的是无参数的doBackOff()。换句话说,代表具体补偿动作是固定的,并不依赖上下文环境。
  3. NoBackOffPolicy类:
    最简单的默认策略,具体延迟为空操作,也就是不补偿,不延迟。
  4. SleepingBackOffPolicy接口:
    有一个withSleeper()方法,传入一个Sleeper。
  5. UniformRandomBackOffPolicy类:
    标准的随机延迟策略,给定最小值,最大值(默认为500L,1500L),会在这个区间里面随机进行补偿延迟。
    7 FixedBackOffPolicy类:
    标准的固定延迟策略,每次延迟固定时间(默认1000L)
  6. ExponentialBackOffPolicy类和ExponentialRandomBackOffPolicy:
    这两个类都是SleepingBackOffPolicy的实现,内部用ThreadWaitSleeper延迟。实现的是延迟指数倍增的效果,区别是ExponentialBackOffPolicy是固定倍增,ExponentialRandomBackOffPolicy加入了随机性。
    例如:
 * {@link ExponentialBackOffPolicy} 延迟序列为: [50, 100, 200, 400, 800]
 *
 * {@link ExponentialRandomBackOffPolicy} 延迟序列可能为: [76, 151, 304, 580, 901] 或者 [53, 190,
 * 267, 451, 815]

retry.context 包

该包只有一个类RetryContextSupport,重试上下文的具体实现。

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981阅读 15,789评论 2 11
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,119评论 9 118
  • “你会理解心理治疗的首要之务,不是去强迫人改变他们的念头;相反的,你要跟随他们的念头,用缓慢的步调来改变它,创造出...
    腻虫阅读 485评论 2 5
  • 人生就像一场梦,活着活着就死了。 是啊,人生如梦。 他们在丰富多彩的日子里翩翩起舞,你却在为了了无生趣的生存烦烦恼...
    声声慢pan阅读 2,730评论 4 3