什么是Spring Retry?
Spring Retry帮你自动重试那些「这次失败、下次可能就成功」的操作,省得你手写循环。
一、Spring Retry 有一个问题
问题:当一次重试流程最终仍然失败时,Spring Retry 默认并不会帮我们完成失败记录等后续处理。本文将深入 Spring Retry 源码,在不改变核心重试机制的基础上进行升级,实现对最终重试失败场景的统一处理。
二、RetryListener 是什么?
RetryListener是框架定义的一个用于监听整个重试生命周期的接口。他不会参与具体的重试逻辑,只是一个观察者角色。在重试开始,失败,成功,以及结束都会进行回调。我们可直接在结束时根据上下文信息进行记录(RetryContext)。
三、RetryListener 的生命周期
因此,RetryListener 可以理解为 Spring Retry 预留的一组扩展钩子。我们可以基于这些回调,在不直接修改业务代码的情况下,因此,RetryListener 可以理解为 Spring Retry 预留的一组扩展钩子。我们可以基于这些回调,在不直接修改业务代码的情况下,对重试过程进行日志记录、监控统计、异常记录以及最终失败处理等。
本文也会基于这一扩展点,对 Spring Retry 的最终失败场景进行二次改造。
创建一个实现RetryListener接口的Bean,Spring Retry框架内部会对此进行管理
@Component public class MysqlRetryListener implements RetryListener { /** * 一次 Retry 流程开始。 */ @Override public <T, E extends Throwable> boolean open( } /** * 每一次失败都会进入这里。 */ @Override public <T, E extends Throwable> void onError( } /** * 整个 Retry 流程结束。 * * throwable == null: * 最终成功 * throwable != null: * 最终失败 */ @Override public <T, E extends Throwable> void close( } }我们只需实现最终窗口close即可
例如
protected <T, E extends Throwable> void doClose( RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) { // 最终成功,不记录 if (throwable == null) { return; } Method method = callback.getInvocation().getMethod(); Object[] args = callback.getInvocation().getArguments(); String name = resolveName(context, callback); String uniqueName = name + "_" + System.currentTimeMillis() + "_" + (int) (Math.random() * 10000); String methodName = method.getName(); String methodClass = method.getDeclaringClass().getName(); String methodArgs = serializeArgs(args); String exceptionClass = throwable.getClass().getName(); String exceptionMessage = throwable.getMessage(); int retryCount = context.getRetryCount(); saveToMysql(...);最终就能够形成一条完整的失败记录。
后续待补充....