SpringCloud之OpenFegin基本介绍及原理分析

本文主要内容:

  1. 简单了解原生Feign、Spring Cloud Open Fegin是什么

一、Spring Cloud Open Fegin介绍

1.1、Feign基础介绍

Feign:是申明式Web服务客户端,基于JAX-RS(javaRest规范)实现的

  • 申明式:通过接口声明、Annotation驱动
  • Web服务:HTTP通讯协议
  • 客户端:用户服务调用存根

Feign可以将一个Service声明为可以被HTTP方式调用,底层基于面向接口的动态代理方式生成实现类,将请求调用委托到动态代理实现类上。

1.2、Spring Cloud Open Fegin基础介绍

Spring Cloud对原生Feign进行封装,使其支持SpringWebMvc,也就是Spring Cloud Open Feign

REST框架 使用场景 请求映射注解 请求参数注解
JAX-RS 客户端、服务端声明 @Path @*Param
Feign 客户端声明 @RequestLine @Param
Spring Web MVC 服务端声明 @ReqeustMapping @RequestParam
SpringCloudOpenFeign 客户端声明 @ReqeustMapping @RequestParam

Spring Cloud Open Feign利用Feign的高扩展性,以及使用标准Spring Web MVC来声明客户端 Java 接口:

  • Feign

    • 注解扩展性

    • HTTP 请求处理

    • REST 请求元信息解析

  • Spring Cloud Open Feign

    • 提供 Spring Web MVC 注解处理
    • 提供 Feign 自动装配

1.3、Spring Cloud Open Fegin的使用

1.3.1、引入Spring Cloud Open Fegin对应jar包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

1.3.2、启用Spring Cloud Open Fegin功能

启用Spring Cloud Open Fegin功能: 在启动类上添加注解@EnableFeignClients注解,并定义要扫描的包名

@EnableFeignClients(basePackages = "com.springcloud.feginclients")
@SpringBootApplication
public class SpringbootApplication {
   
	public static void main(String[] args) {
   
		SpringApplication.run(SpringbootApplication.class, args);
	}
}

1.3.1、声明一个FeignClient

准备一个接口:UserService.class

public interface UserService {
   

    @GetMapping("/getUsers")
    String getUsers();

    @PostMapping("/addUsers")
    int addUser(User user);
}

在定义的basePackages中创建对应的FeignClient,例如:UserServiceFeignClient .calss

  • value: 需要和注册注册中心上的服务名称一致
  • fallback: 请求失败时,会调用fallback指定类中的同名方法
@FeignClient(value = "user-service",
             fallback = UserServiceFeignClient.UserServiceFeignClientFallback.class)
public interface UserServiceFeignClient extends UserService{
   

    @Component
    class UserServiceFeignClientFallback implements UserServiceFeignClient{
   

        @Override
        public String getUsers() {
   
            return "查询用户列表失败,请重试";
        }

        @Override
        public int addUser(User user) {
   
            System.out.println("新增用户失败,请重试");
            return -1;
        }
    }
}

1.3.4、通过接口方式调用FeignClient

通过@Autowired自动注入UserService,SpringCloud会为UserService创建一个动态代理存到IOC容器中

@RestController
@RequestMapping("/user")
public class UserController {
   

    @Autowired
    UserService userService;

   @GetMapping("/getUsers")
    public List<User> getUsers(){
   
        userService.getUsers();
    }

    @PostMapping("/addUsers")
    public int addUser(User user){
   
        userService.addUsers(user);
    }
}

通过使用Spring Cloud Open Fegin我们可以想调用本地方法一样,去请求远程服务接口。下面我们就来分析一下它的原理

二、Spring Cloud Open Fegin原理分析

Spring Cloud Open Fegin的核心原理,可以简单总结为以下意思:Spring Cloud Open Fegin会为标注了@FeignClient注解的接口创建动态代理,然后通过这个代理发送HTTP请求到我们指定分服务端
其中的关键点有两个:

  1. Spring Cloud Open Fegin时如何加载并创建这个代理对象的?(2.1章分析说明)
  2. 代理对象如何完成远程服务调用?(2.2章分析说明)

2.1、为@FeignClient注册动态代理的流程图

Spring Cloud Open Fegin对于@FeignClient注册动态代理的流程大体可以分为以下三步:
在这里插入图片描述

2.1.1、步骤一:FeignClientsRegistrar注册FeignClientFactoryBean

(1)通过@EnableFeignClients启用功能

我在介绍SpringBean装载过程时,介绍过Spring的动态装配Bean:通过@Enable模式+@import方式,可导入三类Class文件

  1. 添加了@Configuration注解的配置类
  2. ImportSelector接口的实现类
  3. ImportBeanDefinitionRegistrar接口的实现类

@EnableFeignClients:通过导入ImportBeanDefinitionRegistrar接口实现类的方式,实现Bean的动态注入,源代码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
   }

增加@EnableFeignClients注解后,Spring会调用FeignClientsRegistrar.registerBeanDefinitions()方法将每一个@FeignClient注册到IOC容器中
FeignClientsRegistrar.registerBeanDefinitions()方法,源码如下:

public void registerBeanDefinitions(AnnotationMetadata metadata,
                                    BeanDefinitionRegistry registry) {
   
    // 如果EnableFeignClients配置了defaultConfiguration
    // 注册一个FeignClientSpecification到IOC中,用于扫描自定义配置类
    registerDefaultConfiguration(metadata, registry);
    
    // 注册FeignClients:会每一个@FeignClient创建代理
    registerFeignClients(metadata, registry);
}

registerDefaultConfiguration方法:注册@EnableFeignClients中定义的defaultConfiguration默认配置(不做分析)

registerFeignClients()方法:会每一个@FeignClient创建代理(下面信息此方法源码)

(2)注册FeignClientFactoryBean到容器中

registerFeignClients.registerFeignClients()方法:会为每一个@FeignClient创建代理,它的核心功能如下:

  1. 定义一个scanner扫描器,并指定扫描路径、筛选条件
    • 扫描路径:根据@EnableFeignClients中配置的参数,获取要扫描的包路径basePackages
    • 设置一个AnnotationTypeFilter过滤器:根据@EnableFeignClients中配置的参数,指定要过滤的文件(添加@FeignClient注解的class文件,或者指定名称的class文件)
  2. 扫描指定basePackages包下,添加@FeignClient注解的class文件:数据会存储到一个Set列表钟,一个class文件对应一个BeanDefinition
  3. 读取每一个BeanDefinition中@FeignClient注解中的属性
  4. 根据@FeignClient注解中的属性,再生成一个FeignClientFactoryBean的BeanDefinition(PS:需要注意,这个BeanDefinition对应的是一个FeignClientFactoryBean(工厂Bean)。在Spring中,工厂Bean是用来创建复杂Bean对象的)
  5. 注册BeanDefinition到容器中(FeignClientFactoryBean的BeanDefinition)
public void registerFeignClients(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
   
    // 定义scanner扫描器,
    ClassPathScanningCandidateComponentProvider scanner = getScanner();
    scanner.setResourceLoader(this.resourceLoader);

    // 获取EnableFeignClients中定义的basePackages
    Set<String> basePackages;

    Map<Strin
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值