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 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容器的类。

其类图如下:

Spring Cloud之FeignClient_第1张图片
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)。

你可能感兴趣的:(Spring Cloud之FeignClient)