资讯动态

Feign:三条 Proxy 代理特点深度解读

发布时间:2026/8/13 23:56:52 来源:尧图企业网站定制
三条 Proxy 代理特点深度解读第 1 条Proxy 代理实例实现了一个加 FeignClient 注解的远程调用接口这句话在说什么你只写了一个接口没有实现类比如FeignClient(nameuser-service)publicinterfaceUserClient{GetMapping(/user/{id})UsergetUser(PathVariable(id)Longid);}Java 里接口是没法直接new的因为接口没有方法体。那 Spring 怎么让你Autowired UserClient userClient拿到一个能用的对象答案就是JDK 动态代理Spring 在运行时凭空生成一个实现了 UserClient 接口的对象这个对象就是Proxy 代理实例。关键点它实现了接口但方法体是动态的UserClientuserClient(UserClient)Proxy.newProxyInstance(classLoader,// 类加载器newClass[]{UserClient.class},// 要实现的接口newFeignInvocationHandler(target,dispatch)// 方法被调用时谁来处理);这个代理对象在类型上确实实现了UserClient所以能赋给UserClient类型变量。但它里面没有你写的任何业务逻辑——所有方法调用都会被转发给FeignInvocationHandler。这就是代理的含义它替接口做事情但事情的具体处理逻辑在别处Handler 里。一句话理解“接口负责声明代理实例负责实现”——Proxy 是接口的影子实现让你能像 new 一个普通类一样使用接口。第 2 条Proxy 代理实例能在内部进行 HTTP 请求的封装以及发送 HTTP 请求这句话在说什么当你调用userClient.getUser(100L)时这个调用没有真的执行任何 Java 逻辑而是被代理拦截转成了发一个 HTTP 请求。调用被FeignInvocationHandler.invoke()拦截后内部做两件事① 封装 HTTP 请求把方法调用翻译成 HTTP 报文// FeignInvocationHandler.invoke() 里MethodHandlerhandlerdispatch.get(method);// 找到这个方法对应的处理器returnhandler.invoke(args);// 处理实际调用再往下SynchronousMethodHandler负责封装请求publicObjectinvoke(Object[]argv){// 把方法参数填进模板生成 Request(HTTP报文)RequestTemplatetemplatebuildTemplateFromArgs.create(argv);// 执行请求ResponseresponseexecuteAndDecode(template);returnresponse;}buildTemplateFromArgs.create(argv)做的事就是封装getUser(100L)→ 把100填进模板占位符{id}→/user/100再拼上 header、body → 生成完整的Request② 发送 HTTP 请求真正把报文发出去// Client.execute() 真正通过底层 HTTP 客户端发送Responseresponseclient.execute(request,options);这一步由feign.Client完成Spring Cloud 默认用 Apache HttpClient 或 OkHttp 把报文发到远程服务。关键点“封装 发送” 全在代理实例内部完成对调用者完全透明。调用者以为自己在调方法实际代理帮你做了把 Java 方法调用翻译成 HTTP 报文再发出去。一句话理解代理实例把方法调用翻译成HTTP 请求并发送——这是它最核心的本领也是让你不用写 HTTP 报文的原因。第 3 条Proxy 代理实例能处理远程 HTTP 请求的响应并且完成结果的解码然后返回给调用者这句话在说什么远程服务返回的是一段HTTP 响应通常是 JSON 字符串而你的方法返回类型是User对象。代理实例要把字符串解码成对象再返回给你。// Decoder.decode() 把响应体转成方法声明的返回类型Objectresultdecoder.decode(response,returnType);// 返回给调用者returnresult;以SpringDecoder为例它内部委托给 Spring 的HttpMessageConverter// 把 response 里的 JSON 字节流 → User 对象Useruser(User)converter.read(User.class,...);关键点从方法调用到拿到结果形成完整闭环调用者视角UseruseruserClient.getUser(100L);// 就这么一行代理内部实际发生了getUser(100L) → 封装HTTP请求(模板填充) → 发送HTTP请求 → 接收HTTP响应(JSON字符串) → 解码成User对象 → 返回给调用者调用者全程不知道 HTTP 的存在它拿到的就是一个普普通通的User对象——就像调用本地方法一样自然。一句话理解代理实例负责收尾把远程返回的 JSON 解码成对象原样还给你让远程调用伪装成了一次普通的方法调用。三句话连起来 Feign 的完整原理把三条串成一条流水线就正好回答了Feign 为什么能让远程调用像本地调用一样① Proxy 实现了 FeignClient 接口 → 让你能假装直接调用接口 ↓ ② Proxy 内部封装 发送 HTTP 请求 → 帮你把方法调用变成HTTP 报文发出去 ↓ ③ Proxy 解码响应并返回 → 把远程返回的 JSON 变成对象还给你一句话总结Proxy 代理实例 一个会翻译的影子实现——调用接口方法①它帮你把方法翻译成 HTTP 报文发出去②再把远程返回的 JSON 翻译回对象还给你③。整个过程对调用者完全透明所以 Feign 能让你不碰 HTTP 报文就完成远程调用。补充对应到源码的位置三条特点对应源码类归属模块① 实现接口生成代理FeignClientFactoryBean/Proxy.newProxyInstancespring-cloud-openfeign-core① 拦截调用FeignInvocationHandlerfeign-core② 封装 发送SynchronousMethodHandler/BuildTemplateByResolvingArgs/Clientfeign-core③ 解码返回DecoderSpringDecoderspring-cloud-openfeign-core

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价