bigywater.tech
Spring · 174

Spring Retry 与 Framework 7 的 @Retryable 同名:次数差 1,启用注解用错不报错

Boot 4 里 Spring Retry 还能用吗?Framework 7 内置的 @Retryable 与它同名,次数怎么算?import 选错、@Enable 选错会怎样?缺 AspectJ 会怎样?这篇在 Spring Boot 4.0.8 上逐个运行。

3 对 4
同样写成 3:Spring Retry 的 maxAttempts = 3 调用 3 次,Framework 7 的 maxRetries = 3 调用 4 次
悄悄不重试
注解与 @Enable 用错时,方法只被调用 1 次,Bean 不是代理,没有任何报错
2.0.13
Boot 3.5.16 与 4.0.8 的依赖管理里 spring-retry 的版本相同

依赖管理

实测 · 本机执行输出
  Boot 3.5.16:受管理,版本 2.0.13
  Boot 4.0.8:受管理,版本 2.0.13

spring-retry 在 Boot 4.0.8 里仍受管理,版本 2.0.13。

Spring Retry

实测 · 本机执行输出
  与重试相关的 Bean 定义:[RetryConfiguration]
  最后抛出 IllegalStateException:fail 3
  方法被调用 3 次;bean 类型 代理(SvcR$$…)

maxAttempts = 3,调用 3 次。

Framework 7

实测 · 本机执行输出
  与重试相关的 Bean 定义:[ResilientMethodsConfiguration, internalConcurrencyLimitProcessor, internalRetryAnnotationProcessor]
  最后抛出 IllegalStateException:fail 4
  方法被调用 4 次;bean 类型 代理(SvcF$$…)

maxRetries = 3,调用 4 次。

用错注解

实测 · 本机执行输出
  与重试相关的 Bean 定义:[RetryConfiguration]
  最后抛出 IllegalStateException:fail 1
  方法被调用 1 次;bean 类型 原始类,没有被代理
  -- 反过来:Spring Retry 的 @Retryable 配 @EnableResilientMethods(没配 @EnableRetry)
  与重试相关的 Bean 定义:[ResilientMethodsConfiguration, internalConcurrencyLimitProcessor, internalRetryAnnotationProcessor]
  最后抛出 IllegalStateException:fail 1
  方法被调用 1 次;bean 类型 原始类,没有被代理

只调用 1 次,没有代理,没有报错。

什么都不启用

实测 · 本机执行输出
  与重试相关的 Bean 定义:[]
  最后抛出 IllegalStateException:fail 1
  方法被调用 1 次;bean 类型 原始类,没有被代理
  -- Framework 注解的方法,什么都不启用
  与重试相关的 Bean 定义:[]
  最后抛出 IllegalStateException:fail 1
  方法被调用 1 次;bean 类型 原始类,没有被代理

结果与用错注解相同,要看 Bean 是不是代理。

同时启用

实测 · 本机执行输出
  与重试相关的 Bean 定义:[ResilientMethodsConfiguration, RetryConfiguration, internalConcurrencyLimitProcessor, internalRetryAnnotationProcessor]
  最后抛出 IllegalStateException:fail 3
  方法被调用 3 次;bean 类型 代理(SvcR$$…)
  -- 同一份配置调用 Framework 注解的方法
  与重试相关的 Bean 定义:[ResilientMethodsConfiguration, RetryConfiguration, internalConcurrencyLimitProcessor, internalRetryAnnotationProcessor]
  最后抛出 IllegalStateException:fail 4
  方法被调用 4 次;bean 类型 代理(SvcF$$…)

两套机制各按各的规则。

缺 AspectJ

实测 · 本机执行输出
  启动失败 ClassNotFoundException:org.aspectj.lang.annotation.Pointcut
  -- 同样没有 aspectj,Framework 的 @EnableResilientMethods
  与重试相关的 Bean 定义:[ResilientMethodsConfiguration, internalConcurrencyLimitProcessor, internalRetryAnnotationProcessor]
  最后抛出 IllegalStateException:fail 4
  方法被调用 4 次;bean 类型 代理(SvcF$$…)

Spring Retry 启动失败,Framework 7 的不受影响。

分步演示

RetryCompare
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(Spring Boot 4.0.8 的 spring-boot 加 spring-retry 2.0.13;Spring Framework 7.0.9;没有使用 Boot 自动配置,每个变体由一个 @Configuration 类加 @ComponentScan 启动,被调用的服务方法总是抛 IllegalStateException,调用次数由静态计数器记录;Bean 是否被代理取自类名里是否含 $$)
    • 没有验证:Spring Retry 的 @Recover 与 RetryTemplate 在 Boot 4 下的行为;Framework 7 的 @Retryable 与 Reactor 返回值的结合;退避时间的实际间隔(见 @Retryable 一篇);maxAttempts 与 maxRetries 之外的其它属性对照;Spring Retry 项目本身在 Spring 官方里的维护状态(只看到依赖管理里还有它,没有查发布说明)
    京ICP备2026067502号-1京公网安备11010502063487号