@Retryable 和 @Recover 使用的时候 注意事项
- @Recover的注解的方法第一个参数需要是 @Retryable 所捕获的重试异常类型;必须是第一个参数
- @Recover注解的方法的 返回值必须 和 @Retryable注解的方法返回值一致
上面两条的原因见文章末尾
最近在使用@Retryable 注解时出现的问题 是 使用了 @Retryable 注解之后;指定了特定的异常进行异常重试机制;设置最大重试次数,当时只设置了@Retryable 注解;但是并没有配合使用 @Recover注解;然后 尽然发现会无限自动重试;大致看了一下;分析如下;如有错误请指出
代码
//当前类中只有 此注解'没有使用 ' @Recover 注解
@Retryable(maxAttempts = 5, value = RetryException.class, backoff = @Backoff(
value = 2000L, multiplier = 1.5
))
查看发现 之所以 无限循环的原因因为没有设置 @Recover 注解;在本类中添加 @Recover 注解就好了;
具体分析的对不对; 只是我的测试
重试机制会走这个方法
org.springframework.retry.support.RetryTemplate#doExecute
代码抽出如下
//org.springframework.retry.support.RetryTemplate#doExecute
//重点看这个代码的倒数第14行的中文注释处
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;
// Allow the retry policy to initialise itself...
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 {
// Give clients a chance to enhance the context...
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);
}
}
/*
* We allow the whole loop to be skipped if the policy or context already
* forbid the first try. This is used in the case of external retry to allow a
* recovery in handleRetryExhausted without the callback processing (which
* would throw an exception).
*/
while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {
try {
if (this.logger.isDebugEnabled(<