Dubbo Filter 通过 invoker.getInterface() 获取服务接口类并反射读取其上的运行时注解,Provider 端写入 RpcContext.getServerAttachment(),Consumer 端写入 getClientAttachment() 实现隐式上下文透传,注解须标注在接口且支持 TYPE 或 METHOD。

在 Dubbo Filter 中通过反射读取 Service 接口上的自定义注解来处理隐式上下文,核心在于:Filter 能拿到调用目标的 Invoker,从中提取接口类型,再用反射获取其声明的注解;注意要区分服务提供方(Provider)和消费方(Consumer)的执行时机与上下文可见性。
获取目标接口类型并反射读取注解
Dubbo 的 Filter 在 invoke() 方法中可通过 invoker.getInterface() 获取被调用的服务接口类(如 UserService.class),这是反射读取注解的起点。该方法返回的是接口 Class 对象,而非实现类,因此能准确命中你定义在接口上的自定义注解。
- 确保你的自定义注解使用
@Retention(RetentionPolicy.RUNTIME)和@Target(ElementType.TYPE)(或支持接口的其他ElementType) - 在 Filter 中调用
invoker.getInterface().getAnnotation(YourCustomAnnotation.class)即可获取注解实例 - 若注解定义在接口的某个方法上,需进一步通过
invoker.getInterface().getMethod(invocation.getMethodName(), ...)获取 Method 对象再读取
在 Provider 端 Filter 中注入隐式上下文
Provider 端 Filter 执行时,服务方法尚未执行,适合从接口/方法注解中提取元数据,并写入 Dubbo 隐式传参上下文(RpcContext.getServerAttachment()),供后续业务逻辑使用。
- 调用
RpcContext.getServerAttachment().set(key, value)写入键值对 - 例如:若注解标记了
@Tenant("finance"),可提取 tenant 值并设为"tenant" → "finance" - 注意:ServerAttachment 是线程绑定的,仅对当前请求生效,无需手动清理
在 Consumer 端 Filter 中透传注解信息
Consumer 端 Filter 需将接口注解解析结果提前写入 RpcContext.getClientAttachment(),Dubbo 会自动将其序列化并透传到 Provider 端。
立即学习“Java免费学习笔记(深入)”;
- 同样先通过
invoker.getInterface()获取接口类,反射读取注解 - 调用
RpcContext.getClientAttachment().put(key, value)设置透传字段 - 避免在 Consumer Filter 中修改
invocation.getAttachments()—— 它不参与隐式传参序列化,仅用于显式传递
注意事项与常见陷阱
反射读取注解本身简单,但实际集成时容易忽略环境差异和生命周期问题:
- Provider 端 Filter 拿到的是服务接口(interface),不是实现类(impl),所以注解必须打在 interface 上才有效
- 泛型接口(如
Service<T>)无法通过getInterface()获取泛型实际类型,需结合invocation.getAttachment("generic")判断是否泛化调用 - Spring Cloud Alibaba 或较新 Dubbo 版本中,
RpcContext默认是 thread-local,但在异步线程(如 CompletableFuture)中需手动RpcContext.restore() - 注解属性含复杂对象时,建议只存 String/Number/Boolean,避免序列化失败


















