共计 2002 个字符,预计需要花费 6 分钟才能阅读完成。
一、前言
在上一篇文章中,我们介绍了 Feign 的基本用法、优势和实践。本篇文章将带你深入源码,了解 Feign 是如何将一个 Java 接口转换成实际的 HTTP 请求。
二、总体调用流程图

三、@FeignClient 背后发生了什么?
1. @EnableFeignClients 启动
在 Spring Boot 启动时,@EnableFeignClients
会触发 FeignClientsRegistrar
的调用,扫描定义了 @FeignClient
注解的接口,并注册到 Spring 容器中,内部通过 FeignClientFactoryBean
以 FactoryBean 方式创建实例。
2. FeignClientFactoryBean 创建代理
@Override
public Object getObject() throws Exception {
return getTarget();
}
<T> T getTarget() {
FeignContext context = this.applicationContext.getBean(FeignContext.class);
Builder builder = feign(context); // 构造 Feign.Builder
Targeter targeter = get(context, Targeter.class);
return targeter.target(this, builder, context); // 调用 target() 创建代理对象
}
四、Feign 代理对象是怎么实现的?
Feign 基于 Java JDK 动态代理把接口转换成代理对象,每次调用方法时会触发 InvocationHandler#invoke()
,而实现是 ReflectiveFeign.FeignInvocationHandler
:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodHandler handler = dispatch.get(method);
return handler.invoke(args); // 调用 SynchronousMethodHandler
}
五、SynchronousMethodHandler 调用逻辑
SynchronousMethodHandler
是 Feign 中大部分请求逻辑的核心实现:
@Override
public Object invoke(Object[] argv) throws Throwable {
RequestTemplate template = buildTemplateFromArgs.create(argv); // 生成请求模板
Request request = targetRequest(template);
Response response = client.execute(request, options); // HTTP 请求
return decode(response); // 转换为实体类
}
buildTemplateFromArgs
根据方法参数 + 注解 生成RequestTemplate
client.execute()
是给定的第三方 HTTP Client (default: Apache HttpClient)decode(response)
通过Decoder
解析返回值
六、其他扩展和配置点
1. Client
可自定义 Client Bean,支持 OkHttp, Apache HttpClient 或自定义实现:
@Bean
public Client feignClient() {
return new OkHttpClient();
}
2. Contract
默认使用 SpringMvcContract,支持 @RequestMapping/ @GetMapping/ @RequestBody 等 Spring MVC 注解解析
3. Encoder / Decoder
支持 JSON / XML / Protobuf 等编解码,可自定义:
@Bean
public Decoder feignDecoder() {
return new JacksonDecoder();
}
4. Retryer
支持重试策略,可配置 Retryer 实现
5. 日志 Logger
高级日志输出,方便调试 HTTP 请求详情
七、总结
本文展示了 Feign 的调用全过程:
- 接口注解 @FeignClient 被扫描 -> 注册 FactoryBean
- FactoryBean 调用 target() -> 构造代理对象
- 代理调用 -> 引入 MethodHandler#invoke
- SynchronousMethodHandler 构造请求 -> HTTP Client 发送 -> Decoder 转换
Feign 为什么能这么简洁?源因就是这套经过精密设计的调用链路和动态代理机制。
如果本文对你有帮助,欢迎点赞、评论!我是 李卷卷,专注Java相关知识输出。感谢阅读!