对比dubbo与fegin不同的点+
1. 为什么看起来像“跳过了接口”因为没有路径在 Feign 里你必须在接口上写GetMapping(/users/{id})因为HTTP 协议必须依靠 URL 路径来路由。但在 Dubbo 里RPC 协议不靠 URL 路径寻址靠的是“接口全限定名 方法名 参数类型”。A 服务消费者你注入的是UserService接口。Spring 注入的不是你写的实现类而是一个**“动态代理对象”**一个假的空壳子。当你写下userService.getUserById(123L)时这个代理对象并没有执行任何 Java 逻辑而是立刻把“接口名com.demo.common.api.UserService”、“方法名getUserById”、“参数值123L”这三样东西打包成二进制数据。通过网络发给 B 服务后B 服务根据“接口名”找到它自己写的UserServiceImpl调用真正的实现再把结果传回来。结论你眼睛看到的userService.xxx()只是一个“替身”在帮你传话实际干活的是远端的 B 服务。接口不仅没有被跳过它反而是 Dubbo 寻址的唯一凭证身份证。所以接口定义必须放在common里A 和 B 必须用同一份class文件包路径要完全一致否则 B 就找不到对应的实现类。2. 关于“返回的类序列化”你的这句话也是完全正确的而且是 Dubbo 生产环境必须特别注意的地方因为 Dubbo 默认走的是TCP 二进制流而不是 HTTP 的 JSON 文本对象要在网络中传输必须实现序列化接口。所以你在common模块里定义的User类必须写上publicclassUserimplementsSerializable{privatestaticfinallongserialVersionUID1L;// ...}特别注意如果 A 和 B 服务的common版本不一致比如 A 的User多了一个age字段B 没有反序列化时可能会报错。所以在 Dubbo 中common模块的版本管理要比 FeignJSON 容错性强严格得多。3. 一次直观的对比让你彻底通透对比维度Feign (HTTP)Dubbo (RPC)Common 里的接口必须写GetMapping路径因为是 HTTP 路由只是一个纯 Java 接口不需要任何路径注解A 服务注入的是什么Autowired注入 Feign 生成的HTTP 代理DubboReference注入 Dubbo 生成的RPC 代理调用时发生了什么把参数转成 JSON拼成 HTTP 请求发给 B 的 Controller把接口名方法名参数序列化通过 TCP 发给 B 的 ServiceB 服务如何接收B 的RestController映射 URL 接收B 的DubboService实现类根据接口名匹配接收返回数据B 返回 JSONA 反序列化成 UserB 返回二进制流A 反序列化成 User强依赖 Serializable4. 终极总结你用一句话概括得非常到位“方法接口提炼到 common 模块的 interface 中然后返回的类序列化”。Feign 版的 common接口里写的是URL 路径 JSON 格式利用 HTTP 的通用性。Dubbo 版的 common接口里写的是Java 类名 方法签名利用 RPC 的高性能二进制传输。