OpenFeign 源码阅读
核心架构
请求处理流程
@FeignClient 接口
│
└─ JDK 动态代理 (FeignInvocationHandler)
│
└─ MethodHandler.invoke()
│
├─ ReflectiveFeign.ParseHandlersByName
│ │
│ └─ 解析方法注解
│ ├─ @RequestMapping / @GetMapping 等
│ ├─ @RequestParam / @PathVariable
│ └─ @RequestBody
│
├─ 构建 RequestTemplate
│ ├─ Method → URL 模板替换
│ ├─ 参数 → Query / Body
│ └─ Header 处理
│
├─ Client.execute(request, options)
│ │
│ ├─ 默认 Client (JDK HttpURLConnection)
│ ├─ ApacheHttpClient
│ ├─ OkHttpClient
│ └─ 负载均衡 Client (FeignBlockingLoadBalancerClient)
│ └─ Spring Cloud LoadBalancer
│
└─ 解码响应
└─ Decoder.decode(response, Type)
├─ SpringDecoder → HttpMessageConverter
└─ ResponseEntityDecoder注册与通信原理
Spring Cloud 自动配置
java
@Configuration
@ConditionalOnClass(Feign.class)
public class FeignAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new DefaultTargeter();
}
@Bean
public FeignContext feignContext() {
return new FeignContext();
}
}动态代理创建
java
@Import(FeignClientsRegistrar.class) // 扫描 @EnableFeignClients
public class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
// 1. 扫描 @FeignClient 注解的接口
Set<String> basePackages = getBasePackages(metadata);
// 2. 为每个接口注册 FactoryBean
for (Class<?> clazz : scannedClasses) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
builder.addPropertyValue("type", clazz.getName());
registry.registerBeanDefinition(
"feign-" + clazz.getSimpleName(), builder.getBeanDefinition());
}
}
}FeignClientFactoryBean
java
public class FeignClientFactoryBean implements FactoryBean<Object> {
@Override
public Object getObject() {
// 1. 获取 Feign.Builder(含编解码、拦截器)
Feign.Builder builder = feignContext.getInstance(type.getName(), Feign.Builder.class);
// 2. 构建 Target
Target<?> target = new Target.HardCodedTarget<>(
type, name, "http://" + name);
// 3. 创建代理
return builder.target(target);
}
}负载均衡集成
FeignBlockingLoadBalancerClient
java
public class FeignBlockingLoadBalancerClient implements Client {
private final Client delegate; // 实际 HTTP 客户端
private final LoadBalancerClient loadBalancer;
@Override
public Response execute(Request request, Request.Options options) throws IOException {
// 1. 从 URL 提取服务名
URI uri = URI.create(request.url());
String serviceName = uri.getHost();
// 2. 负载均衡选择实例
ServiceInstance instance = loadBalancer.choose(serviceName);
// 3. 替换 URL 为实际地址
String realUrl = "http://" + instance.getHost() + ":" + instance.getPort() + uri.getPath();
Request newRequest = Request.create(request.httpMethod(), realUrl, request.headers(), request.body());
// 4. 执行请求
return delegate.execute(newRequest, options);
}
}拦截器机制
自定义请求拦截器
java
@Component
public class FeignAuthInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 添加公共 Header
template.header("Authorization", "Bearer " + getToken());
template.header("X-Request-Id", UUID.randomUUID().toString());
// 参数加密
if (template.body() != null) {
String encrypted = encrypt(template.body());
template.body(encrypted);
}
}
}调用链
RequestInterceptor.apply() → 修改 RequestTemplate
↓
Client.execute() → 发送 HTTP 请求
↓
Decoder.decode() → 解析响应