Feign的整体流程

举报
周杰伦本人 发表于 2022/07/27 11:06:53 2022/07/27
【摘要】 Feign的整体流程 作用 整体流程 FeignClientsRegistrar的registerFeignClient()方法 getTarget()方法 动态代理的创建 总结 Feign的整体流程 作用feign的作用就是根据RPC远程调用的接口生成动态代理实例,然后根据SpringMVC中的方法上的注解生成方法处理器,最终生成HTTP请求,通过feignClient发送给服务端。 整...

Feign的整体流程

作用

feign的作用就是根据RPC远程调用的接口生成动态代理实例,然后根据SpringMVC中的方法上的注解生成方法处理器,最终生成HTTP请求,通过feignClient发送给服务端。

整体流程

feign的整体流程:

FeignClientsRegistrar的registerFeignClient()方法

在启动类添加注解@EnableFeignClients,这个注解中导入了FeignClientsRegistrar类,FeignClientsRegistrar类的主要功能就是通过扫描@FeignClient注解创建FeignClientFactoryBean实例,然后注入到Spring容器中。

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
        String className = annotationMetadata.getClassName();
        BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
        this.validate(attributes);
        definition.addPropertyValue("url", this.getUrl(attributes));
        definition.addPropertyValue("path", this.getPath(attributes));
        String name = this.getName(attributes);
        definition.addPropertyValue("name", name);
        definition.addPropertyValue("type", className);
        definition.addPropertyValue("decode404", attributes.get("decode404"));
        definition.addPropertyValue("fallback", attributes.get("fallback"));
        definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
        definition.setAutowireMode(2);
        String alias = name + "FeignClient";
        AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
        boolean primary = (Boolean)attributes.get("primary");
        beanDefinition.setPrimary(primary);
        String qualifier = this.getQualifier(attributes);
        if (StringUtils.hasText(qualifier)) {
            alias = qualifier;
        }

        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
    }

getTarget()方法

然后代码中通过@Resource等注解使用的时候,会通过FeignClientFactoryBean的getObject()方法来获取到动态代理对象。动态代理对象的生成是通过Feign.Builder的target方法中调用build()方法生成ReflectiveFeign的实例,然后通过newInstance创建最终的RPC动态代理的实例。

<T> T getTarget() {
        FeignContext context = (FeignContext)this.applicationContext.getBean(FeignContext.class);
        Builder builder = this.feign(context);
        String url;
        if (!StringUtils.hasText(this.url)) {
            if (!this.name.startsWith("http")) {
                url = "http://" + this.name;
            } else {
                url = this.name;
            }

            url = url + this.cleanPath();
            return this.loadBalance(builder, context, new HardCodedTarget(this.type, this.name, url));
        } else {
            if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
                this.url = "http://" + this.url;
            }

            url = this.url + this.cleanPath();
            Client client = (Client)this.getOptional(context, Client.class);
            if (client != null) {
                if (client instanceof LoadBalancerFeignClient) {
                    client = ((LoadBalancerFeignClient)client).getDelegate();
                }

                builder.client(client);
            }

            Targeter targeter = (Targeter)this.get(context, Targeter.class);
            return targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url));
        }
    }

动态代理的创建

创建动态代理实例的时候,feign会先创建一个调用处理器,然后每个方法创建方法处理器,方法处理器缓存在调用处理器的dispatch集合中。动态代理实例进行方法调用的时候,Feign根据反射实例从调用处理器的dispatch集合中找到对应的方法处理器,然后进行Http请求。方法处理器生成Request请求,然后交给feign的客户端进行调用,真正使用的时候用LoadBalancerFeignClient,因为它可以进行负载均衡,它还会委托具体的client完成http请求。

总结

这篇文章主要讲了Feign的整体流程,主要是通过@EnableFeignClients注解引入FeignClientsRegistrar类,类中扫描@FeignClient注解,注入FeignClientFactoryBean实例,通过getObject()方法获取动态实例,Feign的远程调用实际上就是通过动态代理来完成的,动态代理的创建是feign根据利用反射机制创建代理对象,然后找到对应的方法处理器发起http请求

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。