feign-core基本使用1.是啥呢?2.怎么玩

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.

本文源码地址-github

聊聊Fein的实现原理

Spring Cloud 整合 Feign 的原理