Spring Cloud之FeignClient

用法

定义好接口,在integration层的接口中,用@FeignClient进行注解。

@FeignClient(value = DependServiceConstants.RFP_CORE_SERVICE_NAME)
public interface ApproveServiceClient  { 
    @org.springframework.web.bind.annotation.PostMapping({"apply/{applyType}/{applyId}"})
    ResultDTO<java.lang.Boolean> approveApply(@org.springframework.web.bind.annotation.PathVariable("applyType") java.lang.Integer integer, @org.springframework.web.bind.annotation.PathVariable("applyId") java.lang.Long aLong, @org.springframework.web.bind.annotation.RequestBody ApproveApplyReq approveApplyReq);
}

在Application入口,用@EnableFeignClients注解。

实现

Feign实现粗读中解释了最原始的Feign是如何实现的Http调用的。下面来看看框架是如何对Feign进一步封装的。

先从注解 @EnableFeignClients 入手。其有一个@Import注解,引入的是FeignClientsRegistrar。从名字可看出,他应该就是把FeignClient注解的对象注入到Spring容器的类。

其类图如下:

image

看其对接口ImportBeanDefinitionRegistrar的实现:

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
            BeanDefinitionRegistry registry) {
    registerDefaultConfiguration(metadata, registry);
    registerFeignClients(metadata, registry);
}

方法registerDefaultConfiguration是将EnableFeignClients的默认配置进行注入,如果有的话。

方法registerFeignClients就是对所有有FeignClient注解的类进行注入的过程。

注入过程不详细列出来了。注意一点是,它向容器注入的是org.springframework.cloud.netflix.feign.FeignClientFactoryBean。

我们知道FactoryBean是Bean的工厂,在获取Bean的实例的时候,实际是调用FactoryBean.getObject来得到的。

@Override
    public Object getObject() throws Exception {
        FeignContext context = applicationContext.getBean(FeignContext.class);
        Feign.Builder builder = feign(context);

        if (!StringUtils.hasText(this.url)) {
            String url;
            if (!this.name.startsWith("http")) {
                url = "http://" + this.name;
            }
            else {
                url = this.name;
            }
            url += cleanPath();
            return loadBalance(builder, context, new HardCodedTarget<>(this.type,
                    this.name, url));
        }
        if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
            this.url = "http://" + this.url;
        }
        String url = this.url + cleanPath();
        Client client = getOptional(context, Client.class);
        if (client != null) {
            if (client instanceof LoadBalancerFeignClient) {
                // not lod balancing because we have a url,
                // but ribbon is on the classpath, so unwrap
                client = ((LoadBalancerFeignClient)client).getDelegate();
            }
            builder.client(client);
        }
        Targeter targeter = get(context, Targeter.class);
        return targeter.target(this, builder, context, new HardCodedTarget<>(
                this.type, this.name, url));
    }

上面是对Url进行处理的过程。最下面Targeter.target最终是调用了Feign.newInstance(Target)。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.1 spring IoC容器和beans的简介 Spring 框架的最核心基础的功能是IoC(控制反转)容器,...
    simoscode阅读 6,753评论 2 22
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,993评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,973评论 6 342
  • IOC和DI是什么? Spring IOC 的理解,其初始化过程? BeanFactory 和 FactoryBe...
    justlpf阅读 3,505评论 1 21
  • 小时候跟着大人去吃席酒的时候吃过拔丝红薯,隔了多年也再没有见过了,有幸突然再次吃到,自然是情感溢出。然而有朋友多次...
    yu菇凉阅读 940评论 0 0