为什么dubbo和openFeign都是通过动态代理的方式发起调用

为什么dubbo和openFeign都是通过动态代理的方式发起调用 因为它们要实现同一个目标让“远程调用”在代码层看起来像“本地方法调用”而实现这个目标的关键设计就是动态代理 方法拦截1 一句话本质Dubbo / OpenFeign “接口 服务入口” 动态代理 “拦截方法调用 → 转换成远程请求”2 为什么必须用动态代理如果不用代理你只能这样写远程调用❌ 传统写法侵入性强Dubbo之前HTTP/Socket手写HttpClient client new HttpClient(); String result client.post( http://user-service/user/1, json );问题1. 代码和通信强耦合 2. 每个接口都要写一堆模板代码 3. 无法统一治理重试/负载均衡/降级❌ 如果不用代理RPC直连UserServiceStub stub new UserServiceStub(); stub.invoke(queryUser, args);问题业务代码必须知道“stub细节” 不符合“面向接口编程”3 动态代理解决什么问题动态代理的核心作用拦截接口方法调用 ↓ 转换成远程请求 ↓ 隐藏网络细节示例用户代码无论 Dubbo 还是 FeignUserService userService; userService.queryUser(1L);看起来是本地方法调用实际发生了什么代理对象拦截 ↓ InvocationHandler.invoke() ↓ 组装请求 ↓ 网络通信 ↓ 返回结果4 Dubbo 为什么用动态代理关键点RPC必须“透明”Dubbo希望开发者 只写接口例如DubboReference UserService userService;实际注入的是JDK Proxy / Javassist Proxy拦截点InvocationHandler.invoke()Dubbo做的事1. 获取方法名 2. 获取参数 3. 查找Provider 4. 负载均衡 5. 序列化 6. Netty发送核心思想接口 服务契约 代理 网络转换器5 OpenFeign 为什么用动态代理Feign的设计更简单HTTP接口 方法映射例如FeignClient(user-service) public interface UserClient { GetMapping(/user/{id}) User get(PathVariable Long id); }Feign代理做什么调用userClient.get(1L);进入代理MethodInterceptor转换为GET /user/1然后HttpClient / OkHttp6 为什么“必须是接口 动态代理”原因1无法修改业务代码如果不用代理UserClientImpl client new UserClientImpl();那你就变成强依赖实现类原因2必须解耦网络逻辑业务只应该关心方法名 参数不应该关心HTTP / TCP / JSON / 序列化原因3统一做横切能力动态代理可以统一插入Dubbo负载均衡 容错 重试 路由 熔断FeignSpring CloudRibbon / LoadBalancer Retry CircuitBreaker Interceptor7 本质对比核心Dubbo Proxy: 方法 → RPC协议 → Netty Feign Proxy: 方法 → HTTP请求 → REST API8 如果不用动态代理会怎样你会变成每个服务手写 HTTP/RPC代码 无法统一治理 无法做到接口透明 代码严重重复9 面试标准总结可以这样回答Dubbo 和 OpenFeign 都采用动态代理的原因是为了实现“接口即服务”的编程模型使远程调用对开发者透明。动态代理可以在不修改业务代码的情况下拦截接口方法调用在运行时统一转换为 RPC 或 HTTP 请求从而屏蔽网络通信细节。同时代理层还能统一增强能力例如负载均衡、重试、熔断、路由和监控等横切逻辑。本质上Dubbo 是将方法调用转为 RPC 调用Feign 是将方法调用转为 HTTP 请求一句话记忆动态代理 把“方法调用”变成“远程调用”的翻译器