Spring Cloud Alibaba-Feign的源码分析

简介: Spring Cloud Alibaba-Feign的源码分析

一、源码分析

1、 源码推演


我们在想为什么我们调用接口StockFeignClient就能调用对应的服务呢?


StockFeignClient接口代码如下:


@FeignClient(name = "msb-stock")//,configuration = StockFeignConfiguration.class)
public interface StockFeignClient {
    /**
     * http://msb-stock/stock/reduce/{productId}
     * @param productId
     * @return
     */
    @GetMapping("/stock/reduce/{productId}")
    String reduce(@PathVariable Integer productId);
}
复制代码


StockFeignClient接⼝打个@FeignClient注解,它是怎么通过接⼝上的信息、找到接⼝的实现类的呢?我们看一下StockFeignClient发现⾥⾯就是⼀些SpringMVC相关的注解信息,⽐如接⼝类和⽅法上的@RequestMapping中、标注了具体访问时的路径以及请求⽅法(GET、PUT、POST、DELETE)是怎样的、@PathVariable标注了应该在请求路径上带上什么变量名、@RequestBody表示POST请求要带上的请求参数。


还有这个@FeignClient中name属性,这些信息一定是构建一个url, 好再@ReqeustMapping中我们知道我们的路径是/stock/reduce/{productId} 并且是一个get请求,


@GetMapping("/stock/reduce/{productId}")
    String reduce(@PathVariable Integer productId);
复制代码


那对应StockFeignClient上的注解@FeignClient注解,可以得到目标服务,也就是本次调用的服务msb-stock



@FeignClient(name = "msb-stock",configuration = StockFeignConfiguration.class)
复制代码


最终根据这些注解信息得到的请求URL信息为:/msb-stock//stock/reduce/12。


⽽⼜因为在SpringCloud体系内,发送⼀次请求都是通过HTTP协议来的,最终我们加上协议后,请求URL为: http://msb-stock//stock/reduce/45465。

分析到这⾥,我们再看下现在还缺什么:http://msb-stock/stock/reduce/45465,这个请求URL中⽬前唯⼀的疑点就在msb-stock上了,总不能就这么尴尬的写个msb-stock来发送请求吧,没有实际的ip和port怕是直接发起请求就报错了,所以肯定是需要将msb-stock解析成具体的ip和port,这样的URL才算是⼀个完整的URL、才能实际的发送有效请求出去。


并且我们是和nacos进行整合的,那么我们需要从nacos中获取所有服务对应的ip和port ,但是我们如果有多个实例那我们是不是需要利用负载均衡器来获取一个我们需要的服务,当然我们feign也整合了ribbon,所以我们底层可以使用ribbon进行负载均衡。



2、源码入口


源码分析的两种思路,一个是@EnableXXX 作为入口,另一个就是springboot的自动装配 xxxAutoConfiguration


image.png

进⼊到EnableFeignClients注解类中,会发现有个@Import注解,这个注解前面我们经常看到,这里导⼊了⼀个⽐较特别的类:FeignClietnsRegistrar,简单翻译下就是Feign的客户端注册器,注册器?这可能是吧@FeignClient注解标记的那些接口类,进行解析然后注入的


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
    String[] value() default {};
    String[] basePackages() default {};
    Class<?>[] basePackageClasses() default {};
    Class<?>[] defaultConfiguration() default {};
    Class<?>[] clients() default {};
}
复制代码



3、扫描@FeignClient标注的类


因为他实现了ImportBeanDefinitionRegistrar 所以我们来看他的registerBeanDefinitions方法


public void registerBeanDefinitions(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
    // 解析默认的配置类EnableFeignClients
   registerDefaultConfiguration(metadata, registry);
    // 注册用@FeignClient标注的接口  
   registerFeignClients(metadata, registry);
}
复制代码


3.1 整体思路分析

image.png

image.png



3.2 获取扫描器


registerFeignClients⽅法⼀进去我们可以看到getScanner⽅法、很明显它就是获取⼀个扫描器,在getScanner⽅法中,发现它new了⼀个


ClassPathScanningCandidateComponentProvider类型的对象,⾥⾯有个⽅法isCandidateComponent,来判断是否是我们需要的


protected ClassPathScanningCandidateComponentProvider getScanner() {
   return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
      @Override
      protected boolean isCandidateComponent(
            AnnotatedBeanDefinition beanDefinition) {
         boolean isCandidate = false;
         // 确定基础类是否独立,即它是一个顶级类或嵌套类(静态内部类)可以独立于封闭类构造。
         if (beanDefinition.getMetadata().isIndependent()) {
             // 判断是否是注解
            if (!beanDefinition.getMetadata().isAnnotation()) {
               isCandidate = true;
            }
         }
         return isCandidate;
      }
   };
}
复制代码


3.3 获取扫描包


image.png


3.4 获取标注@FeignClient的接口并注入容器


获取标注@FeignClient的接口

image.png

image.png


image.png

这里的扫描我们能想起mybatis的扫描。


注入容器


这里设计的类是FeignClientFactoryBean 他是一个FactoryBean 我们获取对象是调用getObject

image.png


总结:

1.以启动类上的@EnableFeignClients为⼊⼝,扫描启动类所在包路径以及该包下所有⼦包中的所有的类


2.从扫描到的类中、筛选出所有打了@FeignClient注解的类


3.解析@FeignClient注解中的属性,创建⼀个BeanDefinition并设置各种属性值,再注⼊到Spring容器中



相关文章
|
7小时前
|
监控 安全 Java
Spring cloud原理详解
Spring cloud原理详解
17 0
|
7小时前
|
消息中间件 负载均衡 Java
【Spring Cloud 初探幽】
【Spring Cloud 初探幽】
16 1
|
7小时前
|
安全 Java Docker
|
7小时前
|
Java 开发者 微服务
Spring Cloud原理详解
【5月更文挑战第4天】Spring Cloud是Spring生态系统中的微服务框架,包含配置管理、服务发现、断路器、API网关等工具,简化分布式系统开发。核心组件如Eureka(服务发现)、Config Server(配置中心)、Ribbon(负载均衡)、Hystrix(断路器)、Zuul(API网关)等。本文讨论了Spring Cloud的基本概念、核心组件、常见问题及解决策略,并提供代码示例,帮助开发者更好地理解和实践微服务架构。此外,还涵盖了服务通信方式、安全性、性能优化、自动化部署、服务网格和无服务器架构的融合等话题,揭示了微服务架构的未来趋势。
35 6
|
7小时前
|
JSON Java Apache
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
|
7小时前
|
负载均衡 Java 开发者
Spring Cloud:一文读懂其原理与架构
Spring Cloud 是一套微服务解决方案,它整合了Netflix公司的多个开源框架,简化了分布式系统开发。Spring Cloud 提供了服务注册与发现、配置中心、消息总线、负载均衡、熔断机制等工具,让开发者可以快速地构建一些常见的微服务架构。
|
7小时前
|
消息中间件 Java RocketMQ
Spring Cloud RocketMQ:构建可靠消息驱动的微服务架构
【4月更文挑战第28天】消息队列在微服务架构中扮演着至关重要的角色,能够实现服务之间的解耦、异步通信以及数据分发。Spring Cloud RocketMQ作为Apache RocketMQ的Spring Cloud集成,为微服务架构提供了可靠的消息传输机制。
30 1
|
7小时前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
19 2
|
7小时前
|
监控 Java Sentinel
Spring Cloud Sentinel:概念与实战应用
【4月更文挑战第28天】在分布式微服务架构中,确保系统的稳定性和可靠性至关重要。Spring Cloud Sentinel 为微服务提供流量控制、熔断降级和系统负载保护,有效预防服务雪崩。本篇博客深入探讨 Spring Cloud Sentinel 的核心概念,并通过实际案例展示其在项目中的应用。
26 0
|
7小时前
|
Cloud Native Java Nacos
Spring Cloud Nacos:概念与实战应用
【4月更文挑战第28天】Spring Cloud Nacos 是一个基于 Spring Cloud 构建的服务发现和配置管理工具,适用于微服务架构。Nacos 提供了动态服务发现、服务配置、服务元数据及流量管理等功能,帮助开发者构建云原生应用。
21 0