Feign的底层原理
- 1 @EnableFeignClients
- 2 根据接口上的注解创建RequestTemplate
- 3 发送请求
1 @EnableFeignClients
这个注解标注在springboot的启动类上,作用是开启feign接口扫描

FeignClientsRegistrar.registerFeignClients()扫描被@FeignClient标识的接口生成代理类
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet();
Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
new AnnotationTypeFilter(FeignClient.class);
Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
if (clients != null && clients.length != 0) {
Class[] var13 = clients;
int var15 = clients.length;
for(int var17 = 0; var17 < var15; ++var17) {
Class<?> clazz = var13[var17];
candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
}
} else {
ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
Set<String> basePackages = this.getBasePackages(metadata);
Iterator var9 = basePackages.iterator();
while(var9.hasNext()) {
String basePackage = (String)var9.next();
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
}
Iterator var14 = candidateComponents.iterator();
while(var14.hasNext()) {
BeanDefinition candidateComponent = (BeanDefinition)var14.next();
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String name = this.getClientName(attributes);
this.registerClientConfiguration(registry, name, attributes.get("configuration"));
this.registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
2 根据接口上的注解创建RequestTemplate
当controller调用feign代理类时,代理类会调用SynchronousMethodHandler.invoke()创建RequestTemplate(url、requestMethod、body)
3 发送请求
接着通过RequestTemplate创建Request,然后client(HttpClient、OkHttp、URLConnection)使用Request发送请求