1. 是啥呢?
Feign 是一个HTTP请求的轻量级的客户端框架。通过接口 + 注解
的方式发起HTTP请求调用,面向接口编程;类似于dubbo, 实现RMI(远程过程调用);
2. 怎么玩?
2.1 项目初始化
构建一个spring-boot项目
2.2 引入jar
<properties>
<java.version>1.8</java.version>
<spring-cloud-version>2.1.0.RELEASE</spring-cloud-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${spring-cloud-version}</version>
</dependency>
</dependencies>
复制代码
2.3 服务接口
/**
* 吃饭
*/
@FeignClient(name = "yiyi-feign-provider", path = "/eat")
public interface EatService {
/**
* 吃
*/
@GetMapping("/apple")
String eatApple();
/**
* 吃🍊
*/
@GetMapping("/orange")
String eatOrange(@RequestParam("who") String who);
}
复制代码
2.4 junit单测
public class FeignTest {
@Test
public void eatApple() {
EatService eatService = Feign.builder()
.contract(new SpringMvcContract())
.target(EatService.class, "http://localhost:18081/eat");
String s = eatService.eatApple();
System.out.println(" eatService.eatApple() = " + s);
}
}
复制代码
2.5 运行结果
注:运行前请启动另一个服务,当服务提供方,保证http://localhost:18081/可用性;可用参考本文源码启动就OK;
3. 原理追踪
3.1 准备
从怎么玩中我们看到,feign-core ,必须要有 接口;接口不能直接运行;so,运行的一定是个代理;
代理怎么实现呢?没接口可能是cglib , 有了那一定是jdk-proxy 这一套;
jdk-proxy 核心逻辑如下:
Proxy.newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h);
复制代码
ClassLoader : 类加载器,这个一般都是应用类加载器;
Class<?>[] : 这个就是我们定义的接口;
InvocationHandler : 这个一般需求重写,分析原理着重看这个的实现就OK;
3.2 debug看流程
\
目的:我们debug 最重要的找到 在哪里生成了代理对象,即哪个地方调用了Proxy.newProxyInstance 方法;源码个人感觉有点冗余,就不粘贴了,直接看构建流程图;
\
核心对象 FeignInvocationHandler、HardCodedTarget、MethodHandler、Method 关系如下;
注:看源码可以不用每行都看,要有自己对框架的理解,一定要学会debug!!!
4. 常见使用问题汇总
A bean with that name has already been defined and overriding is disabled.
原因: 存在一个以上的Feign接口指向同一个微服务
解决:
application.properties 中加入以下配置
spring.main.allow-bean-definition-overriding=true
复制代码
参见
关于OpenFeign使用后出现A bean with that name has already been defined and overriding is disabled.
近期评论