是什么
Feign是一个由SpringCloud提供的RPC框架,可以实现系统间声明式调用,说白了就是像掉本地方法一样调其他系统提供的服务或者可以说是接口。理解了RPC就能理解Feign是什么。
能干什么
就干一件事,系统间RPC调用
怎么干
Feign使用起来特别简单,如下:
1、把Feign引入进项目
<groupId>org.springframework.cloud
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
1、加个注解@EnableFeignClients在SpringBoot启动类上,用于扫描和注册feign客户端bean定义;
2、用注解@FeignClient定义Feign客户端,就是写个实现RPC调用的接口,类似这样的:
@FeignClient(value ="microservice-provider-user",fallbackFactory = ProviderServiceFallbackFactory.class)
public interface ProviderService {
@RequestMapping(value ="/fallback/{id}",method = RequestMethod.GET)
UserfindById(@PathVariable("id")int id);
}
3、在使用的地方,直接@Autowired注入进来,Spring会自动搞一套东西,然后就可以像调方法一样调这个接口了。
以上只是简单说了说Feign怎么使用,其实它还有很多的配置,和使用方式,现在介绍一下比较常用的配置和使用场景
既然是声明式调用工具,那Feign就能够简化系统间相互调用的实现方式。回顾以往开发接口的形式,是先约定接口逻辑,并以接口文档形式定板,开发,调试,最终上线。引入Feign以后,并不能简化这个流程,但是,可以简化开发过程,因为我们只需要按照约定的接口形式(比如是get还是post,请求/返回报文格式,一般都是javabean形式)开发一个接口即可。我们可以发现,Feign已经尽自己所能,解放程序员的开发工作,因为接口逻辑即为业务逻辑,这个是不能通过技术进行解决简化的(只能是通过不同系统间的 开发-业务-产品 之间沟chao通jia,得到的,Feign并不能帮你去打产品经理)。
现在我们可以使用Swagger来生成接口文档,但我们在生产环境并没有使用,因为接口文档还是由相关人员维护的,毕竟每家公司都有自己的接口文档形式,甚至是每个系统都不一样。
我们发布一个子项目,该项目就是一个FeignClient的接口集合,也是系统向外暴露的服务API,我们将它打包发布。想要使用该系统服务的其他系统,可以将该包引入自己的系统,便可以实现RPC调用了。
以上只是简单说了一下独立使用Feign的情况,其实Feign独立使用并没有太多的意义,而是和Ribbon,Hystrix集合起来使用,他们是“吉祥三宝”,后续我会写一个组合使用的文章来详细介绍。
原理
我们在使用Feign的时候,会觉得好方便,好简单啊,只需要定义一个接口和方法,就能实现RPC调用。这是因为SpringCloud在后台为我们默默的做了很多事情,现在我们来抽丝剥茧,探究一下SpringCloud到底为我们做了什么。
首先,我们在SpringBoot启动类里加了注解@EnableFeignClients,他的作用就是扫描给定的包下带注解@FeignClient的类,然后基于面向接口的动态代理方式生成实现类。话不多说,上代码
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
//省略
}
@Import({FeignClientsRegistrar.class})这个注解比较重要,因为FeignClientsRegistrar这个类是@EnableFeignClients的核心入口,其中有个核心的方法registerBeanDefinitions
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
this.registerDefaultConfiguration(metadata, registry);
this.registerFeignClients(metadata, registry);
}
下面这两个方法的执行步骤我就不贴代码了,网上有一张图可以比较完整的描述整个过程,当一下伸手党。其实spring做了主要是读取注解的配置,然后根据配置进行动态代理返回一个代理对象,由这个代理对象进行http接口调用操作。