核心组件与概念
读者在阅读Feign
源码时,可以沿着两条路线进行,一是FeignServiceClient
这样的被@FeignClient
修饰的接口类如何被创建出来,也就是其Bean对象是如何被构建的,二是调用FeignServiceClient
对象的响应方法时,Feign
是如何发送网络请求的。而Feign
相关的类也可以以此来进行分类,一部分是用来初始化相应的Bean示例的,一部分是用来在调用方法时发送网络请求的。
上图是Feign
相关的关键类图,其中比较重要的类为FeignClientFactoryBean
,FeignContext
,SynchronousMethodHandler
。其中FeignClientFactoryBean
可以创建@FeignClient
修饰的接口类Bean示例;FeignContext
作为配置的上下文环境,保存着相关组件的不同实例,这些示例都是按照不同的FeignConfiguration
所构造出来的;SynchronousMethodHandler
是MethodHandler
的子类,可以在相应方法被调用时发送网络请求,然后再将请求响应转化为函数返回值进行输出。
图是后续源码讲解的流程图,Feign
会首先进行相关BeanDefinition的动态注册,然后当spring
容器注入相关实例时会进行实例的初始化,最后当相关实例的函数被调用时会进行发送网络请求。
动态注册BeanDefinition
Feign
可以通过多种方式进行自定义配置,配置的变化会导致接口类初始化时使用不同的实现类,从而控制Feign
的相关行为,比如说网络请求的编解码,压缩和日志处理。可以说,了解Feign
配置和实例初始化的流程和原理对于我们学习和使用Feign
有着至关重要的作用,而且Spring Cloud
的所有项目的配置和实例初始化过程原理基本相同,了解了Feign
的原理,就可以触类旁通,一通百通了。
在快速入门一节已经介绍了@EnableFeignClients
的基本作用,它就像是Feign
的总开关,一切Feign
的相关的操作都是从它开始的。@EnableFeignClients
有三个作用,一是是引入FeignClientsRegistrar
;二是指定扫描FeignClient的package信息,就是指定你所有FeignClient所在的包名;三是指定FeignClient的自定义配置类。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
//ImportBeanDefinitionRegistrar的子类,用于处理@FeignClient注解。
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
/**
* 下面三个函数都是为了指定需要扫描的basepackage。
**/
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
/**
* 指定自定义feign client的自定义configuration,可以配置Decoder,Encoder和Contract,FeignClientsConfiguration是默认的配置类
*/
Class<?>[] defaultConfiguration() default {};
/**
* 指定被@FeignClient修饰的类,如果不为空,那么路径自动检测机制会被关闭
* List of classes annotated with @FeignClient. If not empty, disables classpath scanning.
* @return
*/
Class<?>[] clients() default {};
}
FeignClientsRegistrar
是ImportBeanDefinitionRegistrar
的子类,Spring用ImportBeanDefinitionRegistrar
来动态注册BeanDefinition。Feign
通过FeignClientsRegistrar
来处理@FeignClient
修饰的FeignClient类,将这些接口的BeanDefinition注册到Spring容器中。这样就可以使用@Autowired
来自动装载这些FeignClient的Bean实例,从而可以调用这些实例的方法发送网络请求。
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
//....代码有删减
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//从EnableFeignClients的属性值来构建Feign的自定义Configuration进行注册
registerDefaultConfiguration(metadata, registry);
//扫描package,注册被@FeignClient修饰的接口类的bean信息
registerFeignClients(metadata, registry);
}
//代码有删减
}
FeignClientsRegistrar
的registerBeanDefinitions
函数主要做了两个事情,一是注册@EnableFeignClients
提供的自定义配置类中的相关Bean信息,二是根据@EnableFeignClients
提供的包信息扫描被@FeignClient
修饰的FeignCleint接口类,然后进行注册。
下面的文章将会关注其他核心类的实现。