Spring-retry详解( 四 )

该方法会返回 @Retryable 最终使用的处理类 , 我们重点看一下 getStatelessInterceptor 的处理 , getStatefulInterceptor 中多了 @CircuitBreaker 熔断相关的处理 。
private MethodInterceptor getStatelessInterceptor(Object target, Method method, Retryable retryable) {//生成 RetryTemplate , 同时主持 listenerRetryTemplate template = createTemplate(retryable.listeners());//设置重试策略template.setRetryPolicy(getRetryPolicy(retryable));//设置退避策略template.setBackOffPolicy(getBackoffPolicy(retryable.backoff()));//通过 StatelessRetryInterceptorBuilder 创建 RetryOperationsInterceptor 拦截 , 初始化重试模板等信息return RetryInterceptorBuilder.stateless().retryOperations(template).label(retryable.label()).recoverer(getRecoverer(target, method)).build();}在回头看看 getStatefulInterceptor 方法
private MethodInterceptor getStatefulInterceptor(Object target, Method method, Retryable retryable) {RetryTemplate template = createTemplate(retryable.listeners());template.setRetryContextCache(this.retryContextCache);//获取方法上的 CircuitBreaker 注解CircuitBreaker circuit = AnnotatedElementUtils.findMergedAnnotation(method, CircuitBreaker.class);if (circuit == null) {//如果熔断参数不为空 , 则处理相关参数 , 返回响应的拦截处理方 , 如果为空  , 则处理非熔断的有状态重试circuit = findAnnotationOnTarget(target, method, CircuitBreaker.class);}if (circuit != null) {//处理 CircuitBreaker 注解中的 retryable 相关参数 , 获得重试策略RetryPolicy policy = getRetryPolicy(circuit);CircuitBreakerRetryPolicy breaker = new CircuitBreakerRetryPolicy(policy);breaker.setOpenTimeout(getOpenTimeout(circuit));breaker.setResetTimeout(getResetTimeout(circuit));template.setRetryPolicy(breaker);template.setBackOffPolicy(new NoBackOffPolicy());String label = circuit.label();if (!StringUtils.hasText(label)) {label = method.toGenericString();}return RetryInterceptorBuilder.circuitBreaker().keyGenerator(new FixedKeyGenerator("circuit")).retryOperations(template).recoverer(getRecoverer(target, method)).label(label).build();}RetryPolicy policy = getRetryPolicy(retryable);template.setRetryPolicy(policy);template.setBackOffPolicy(getBackoffPolicy(retryable.backoff()));String label = retryable.label();return RetryInterceptorBuilder.stateful().keyGenerator(this.methodArgumentsKeyGenerator).newMethodArgumentsIdentifier(this.newMethodArgumentsIdentifier).retryOperations(template).label(label).recoverer(getRecoverer(target, method)).build(); }重试逻辑及策略实现RetryTemplate 的 doExecute 方法 。
protected <T, E extends Throwable> T doExecute(RetryCallback<T, E> retryCallback,RecoveryCallback<T> recoveryCallback, RetryState state)throws E, ExhaustedRetryException {// 获得重试策略RetryPolicy retryPolicy = this.retryPolicy;// 退避策略BackOffPolicy backOffPolicy = this.backOffPolicy;//新建一个 RetryContext 来保存本轮重试的上下文,允许重试策略自行初始化RetryContext context = open(retryPolicy, state);if (this.logger.isTraceEnabled()) {this.logger.trace("RetryContext retrieved: " + context);}// Make sure the context is available globally for clients who need// it...RetrySynchronizationManager.register(context);Throwable lastException = null;boolean exhausted = false;try {//给监听器发送一条信息 。boolean running = doOpenInterceptors(retryCallback, context);if (!running) {throw new TerminatedRetryException("Retry terminated abnormally by interceptor before first attempt");}// Get or Start the backoff context...BackOffContext backOffContext = null;Object resource = context.getAttribute("backOffContext");if (resource instanceof BackOffContext) {backOffContext = (BackOffContext) resource;}if (backOffContext == null) {backOffContext = backOffPolicy.start(context);if (backOffContext != null) {context.setAttribute("backOffContext", backOffContext);}}//判断能否重试 , 就是调用 RetryPolicy 的 canRetry 方法来判断 。//这个循环会直到原方法不抛出异常 , 或不需要再重试while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {try {if (this.logger.isDebugEnabled()) {this.logger.debug("Retry: count=" + context.getRetryCount());}lastException = null;return retryCallback.doWithRetry(context);}catch (Throwable e) {//方法抛出了异常lastException = e;try {//记录异常信息registerThrowable(retryPolicy, state, context, e);}catch (Exception ex) {throw new TerminatedRetryException("Could not register throwable",ex);}finally {//调用 RetryListener 的 onError 方法doOnErrorInterceptors(retryCallback, context, e);}//再次判断能否重试if (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {try {//如果可以重试则走退避策略backOffPolicy.backOff(backOffContext);}catch (BackOffInterruptedException ex) {lastException = e;// back off was prevented by another thread - fail the retryif (this.logger.isDebugEnabled()) {this.logger.debug("Abort retry because interrupted: count="+ context.getRetryCount());}throw ex;}}if (this.logger.isDebugEnabled()) {this.logger.debug("Checking for rethrow: count=" + context.getRetryCount());}if (shouldRethrow(retryPolicy, context, state)) {if (this.logger.isDebugEnabled()) {this.logger.debug("Rethrow in retry for policy: count="+ context.getRetryCount());}throw RetryTemplate.<E>wrapIfNecessary(e);}}/** A stateful attempt that can retry may rethrow the exception before now,* but if we get this far in a stateful retry there's a reason for it,* like a circuit breaker or a rollback classifier.*/if (state != null && context.hasAttribute(GLOBAL_STATE)) {break;}}if (state == null && this.logger.isDebugEnabled()) {this.logger.debug("Retry failed last attempt: count=" + context.getRetryCount());}exhausted = true;//这里会查看是否有兜底方法 , 有就执行 , 没有就抛出异常return handleRetryExhausted(recoveryCallback, context, state);}catch (Throwable e) {throw RetryTemplate.<E>wrapIfNecessary(e);}finally {close(retryPolicy, context, state, lastException == null || exhausted);//关闭 RetryListenerdoCloseInterceptors(retryCallback, context, lastException);RetrySynchronizationManager.clear();} }


推荐阅读