可以自定义注解+ aop 实现轻量级重试功能:定义含 maxattempts、delay、multiplier、retryableexceptions 和 ignoreexceptions 参数的 @retryable 注解,并通过切面拦截执行重试逻辑。

Java 中可以通过自定义注解 + AOP(切面)的方式,实现类似 Spring Retry 的 @Retryable 功能,让系统在方法失败时自动重试,达到轻量级容灾效果。核心思路是:定义注解声明重试规则 → 编写切面拦截带注解的方法 → 在切面中按策略执行重试逻辑。
定义可配置的重试注解
先创建一个自定义注解,支持常见重试参数:
- maxAttempts:最大重试次数(含首次调用)
- delay:首次失败后延迟毫秒数(固定等待)
- multiplier:退避倍率(用于指数退避,如 2.0 表示每次延迟翻倍)
- retryableExceptions:哪些异常触发重试(白名单)
- ignoreExceptions:哪些异常直接抛出、不重试(黑名单)
示例定义:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Retryable {
int maxAttempts() default 3;
long delay() default 1000;
double multiplier() default 1.0;
Class extends Throwable>[] retryableExceptions() default {Exception.class};
Class extends Throwable>[] ignoreExceptions() default {};
}
编写切面实现重试逻辑
使用 @Around 拦截标注了 @Retryable 的方法,手动控制执行与重试流程:
- 获取注解配置,初始化当前延迟时间(
currentDelay = delay) - 循环执行方法(最多
maxAttempts次),每次捕获异常 - 若抛出的异常属于
ignoreExceptions,立即抛出不重试 - 若属于
retryableExceptions且未达最大次数,则休眠currentDelay后重试,并更新延迟(如乘以 multiplier) - 若成功或重试耗尽,返回结果或最终异常
注意:需用 Thread.sleep() 或更优的 ScheduledExecutorService 控制延迟,避免阻塞主线程(尤其在 Web 场景下需谨慎)。
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
注册切面并启用代理
确保切面被 Spring 扫描到,并开启 AspectJ 代理:
- 切面类加上
@Aspect和@Component - 主配置类或启动类添加
@EnableAspectJAutoProxy - 确保目标方法是 Spring 管理的 Bean(非 this. 调用),否则 AOP 不生效
简单切面骨架示例:
@Aspect
@Component
public class RetryAspect {
@Around("@annotation(retryable)")
public Object doRetry(ProceedingJoinPoint joinPoint, Retryable retryable) throws Throwable {
// 实现上述重试逻辑
return ...;
}
}
增强健壮性的小技巧
生产环境建议补充以下细节:
- 记录每次重试日志(如“第 2 次重试,延迟 2000ms”),便于问题追踪
- 支持异步重试(用
CompletableFuture或线程池),避免阻塞调用方 - 加入熔断判断(如连续 N 次失败后暂时跳过重试),防止雪崩
- 允许通过 SpEL 表达式动态计算参数(如
delay = "#{@config.retryDelay}"),提升灵活性
不复杂但容易忽略:重试只对**幂等操作**安全,务必确认被重试方法具备幂等性(如查询、带唯一键的插入、状态机推进等),否则可能引发数据重复或不一致。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










