Backend Development 7 min read

Mastering Spring Retry: How @Retryable Simplifies Robust Backend Calls

This article explains how Spring Boot's spring-retry module and the @Retryable annotation enable clean, annotation‑driven retry logic for common failure scenarios, covering configuration, code examples, recovery handling with @Recover, and important usage precautions.

macrozheng
macrozheng
macrozheng
Mastering Spring Retry: How @Retryable Simplifies Robust Backend Calls

Preface

In real work, retry is a very common scenario, such as sending a message failure, remote service call failure, or lock acquisition failure.

Sending message fails.

Calling remote service fails.

Lock acquisition fails.

These errors may be caused by network fluctuations; after waiting, a retry can succeed. Typically developers use try/catch or while loops, but those approaches lack uniformity and require extra code. The spring-retry library allows retry functionality to be added via annotations without intruding on existing business logic.

What is @Retryable?

spring-retry is a utility module that helps handle retries in a standard way. All configuration is based on simple annotations.

Usage Steps

POM Dependency

<code>&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.retry&lt;/groupId&gt;
  &lt;artifactId&gt;spring-retry&lt;/artifactId&gt;
&lt;/dependency&gt;
</code>

Enable @Retryable

<code>@EnableRetry
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}
</code>

Add @Retryable to a Method

<code>import com.mail.elegant.service.TestRetryService;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import java.time.LocalTime;

@Service
public class TestRetryServiceImpl implements TestRetryService {

    @Override
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 1.5))
    public int test(int code) throws Exception {
        System.out.println("test被调用,时间:" + LocalTime.now());
        if (code == 0) {
            throw new Exception("情况不对头!");
        }
        System.out.println("test被调用,情况对头了!");
        return 200;
    }
}
</code>

Explanation of annotation parameters:

value

: retry only for the specified exception types.

include

: same as

value

, default empty; when both

include

and

exclude

are empty, all exceptions are retried.

exclude

: exceptions that should not be retried.

maxAttempts

: maximum number of retry attempts, default is 3.

backoff

: retry waiting strategy using

@Backoff

. The default

value

is 1000 ms; in the example it is set to 2000 ms.

multiplier

defaults to 0 (fixed 1 s delay). Setting

multiplier

to 1.5 makes the delays 2 s, 3 s, and 4.5 s for successive attempts.

When retries are exhausted,

RetryOperations

can delegate to a

RecoveryCallback

. Spring‑retry also provides the

@Recover

annotation for handling the situation after an

@Retryable

method fails. If no recovery method is defined, the exception is re‑thrown.

@Recover

<code>@Recover
public int recover(Exception e, int code) {
    System.out.println("回调方法执行!!!!");
    // log to database or perform other actions
    return 400;
}
</code>

Key points for a

@Recover

method:

The return type must match the corresponding

@Retryable

method.

The first parameter must be a

Throwable

(usually the same exception type configured in

@Retryable

).

The method must reside in the same class as the retry method.

Precautions

Because it is based on AOP, self‑invocation of methods in the same class is not supported.

If retry fails and you need further processing via

@Recover

, the retry method must return

void

.

Method bodies should not contain

try/catch

; let exceptions propagate outward.

The

@Recover

method’s first parameter must be the exception type thrown by the

@Retryable

method; otherwise it will not be recognized.

Conclusion

This article introduced the use of Spring Boot's

Retryable

annotation, its typical scenarios, and important precautions, demonstrating that it is a useful tool when retry logic is required.

Javabackend developmentSpring BootAnnotationsRetryableSpring Retry
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.