Spring AOP中多个Resilience4j注解执行顺序需显式配置order值,否则按字母序导致业务逻辑错乱;应拆分高耦合注解、避免共享增强器、慎用元注解嵌套。

这类问题本质是 Spring AOP 代理链中多个切面增强逻辑的执行顺序失控,不是注解本身“打架”,而是它们生成的 Advice 在织入时缺乏明确优先级,导致行为不符合预期。关键不在“避免挂多个注解”,而在“确保它们按业务语义正确串行”。
明确注解执行顺序(最直接有效)
Resilience4j 等基于 Spring AOP 的注解框架默认按注解类名字母序执行,这和业务逻辑无关。必须显式配置优先级:
- 在 application.yml 中设置执行顺序数值,越小越先执行:
resilience4j:
aop:
order:
circuitBreaker: 1
retry: 2
timeout: 3 - 若需动态控制,可自定义 Resilience4jAopProperties Bean,在 Java 配置类中返回带 order 映射的实例。
拆分高耦合注解组合(降低风险)
当 @Retry、@CircuitBreaker、@RateLimiter 同时出现在一个方法上,不仅顺序敏感,fallback 行为、异常捕获范围也容易重叠。建议:
- 把核心业务逻辑抽成独立 service 方法,只加最外层注解(如 @CircuitBreaker);
- 重试、限流等策略下沉到内部调用链,用编程式 API(如 Retry.decorateSupplier)控制,避免全靠声明式注解堆叠;
- 对关键路径做单元测试,验证异常触发后是否真正进入 retry 而非被 circuit breaker 直接熔断跳过。
检查注解是否共享同一类增强器(排查隐性冲突)
某些自定义注解可能复用相同的 Aspect 类或 Advisor,导致多次织入同一逻辑。可通过以下方式确认:
- 启动时加 -Dspring.aop.proxy-target-class=true 并开启 DEBUG 日志,搜索 “Advised” 或 “createProxy”;
- 用 Arthas 的 trace 命令观察目标方法实际被哪些 Advice 包裹,例如:
trace com.example.Service doSomething '@Retry' '@CircuitBreaker' - 检查是否误将多个注解指向了同一个切点表达式(如都用了 @annotation(io.github.resilience4j.retry.Retry)),造成重复代理。
慎用 @AliasFor 或元注解嵌套(防语义覆盖)
如果自己封装了复合注解(比如 @MyResilient),内部用 @AliasFor 引入多个底层注解,要特别注意:
- @AliasFor 不会自动合并配置,同名属性(如 fallbackMethod)若未显式指定,可能被后解析的注解覆盖;
- 避免在元注解中同时包含 @Retry 和 @CircuitBreaker —— 这会让 order 配置失效,因为框架只识别顶层注解;
- 更稳妥的做法是:元注解只做标记,具体策略通过配置中心或 @ConfigurationProperties 注入,运行时动态绑定。

















