自定义注解仅声明保护意图,实际限流熔断由aop切面通过反射读取注解参数并分别对接sentinel规则注册或hystrixcommand手动构造来实现,需统一拦截controller层入口且避免sentinel与hystrix双重包装。

自定义注解本身不直接执行限流或熔断,它的作用是“声明意图”——告诉框架:这个接口需要被保护,并附带哪些规则参数。真正起作用的是背后的AOP切面或拦截器,通过反射读取注解属性,再动态注册到Sentinel资源或封装为HystrixCommand。
注解设计要覆盖核心控制维度
一个实用的自定义注解需同时兼容Sentinel和Hystrix语义,至少包含以下字段:
-
resourceName:Sentinel中资源唯一标识(如
"order/create"),也是Hystrix中commandKey的基础来源 - fallbackMethod:降级方法名,要求与当前类中同签名的public方法匹配(Hystrix强制,Sentinel可选)
-
blockHandler:仅Sentinel使用,处理被流控/熔断时的阻塞逻辑,支持额外传入
BlockException - flowThreshold / degradeThreshold:分别对应QPS阈值和慢调用比例,用于初始化规则(适用于规则静态化场景)
- fallbackClass:指定降级类(当fallbackMethod不在当前类时),避免Spring AOP代理失效问题
反射读取+动态注册Sentinel规则
在切面中获取注解后,用反射提取参数,再调用Sentinel API注册资源和规则:
- 调用
SphU.entry(resourceName)标记资源入口(需配合@SentinelResource或自行包装) - 构建
FlowRule并用FlowRuleManager.loadRules()加载;若需持久化,应对接Nacos等数据源而非每次请求都load - 注意:Sentinel Dashboard推送的规则会覆盖代码中硬编码的规则,因此生产环境建议关闭自动注册,改用控制台统一管理
反射构造HystrixCommand对象
Hystrix不支持运行时修改@HystrixCommand注解参数,所以需绕过注解,手动创建命令实例:
- 通过
Method.getAnnotation(HystrixCommand.class)读取原始配置(如有) - 使用
HystrixCommand.Setter构建配置:设置withGroupKey、withCommandKey、withFallbackMethod等 - 将业务逻辑封装进
run(),降级逻辑封装进getFallback(),再执行execute()或queue() - 关键点:fallbackMethod必须是当前对象的方法,且签名兼容(返回类型一致,参数可少于原方法)
统一拦截入口避免重复织入
Spring MVC中,推荐在HandlerInterceptor.preHandle或自定义@Aspect切@RequestMapping子类注解(如@GetMapping):
- 优先检查方法上是否存在你的自定义注解,有则触发保护逻辑
- 对Controller层方法生效,不建议切Service层——那会干扰事务和重试语义
- 若同时引入Sentinel和Hystrix,需明确优先级(例如Sentinel负责网关/入口限流,Hystrix负责下游调用熔断),避免双重包装导致统计失真










