OpenFeign源码精解

本文深入解析OpenFeign的核心组件,包括@FeignClient注解接口的实例化过程和网络请求的实现。通过分析FeignClientFactoryBean、FeignContext和SynchronousMethodHandler等关键类,揭示了OpenFeign如何创建接口实例以及如何执行HTTP请求。了解这些细节有助于更好地理解和使用OpenFeign。
摘要由CSDN通过智能技术生成

OpenFeign的核心组件

通常我们在阅读OpenFeign的源码时,可以通过两条路来理解:

1)@FeignClient注解修饰的接口类是如何创建,实例化的

2)调用FeignServiceClient对象的网络请求的相关函数时,OpenFeign是怎么发送请求的

因此,OpenFeign相关的类也可以大致归为:类实例化相关的发送网络请求相关的

如下图(OpenFeign关键类类图):

其中,比较重要的是:Fe ignClientFactoryBean、FeignContext和SynchronousMethodHandler。

1)FeignClientFactoryBean:是创建 FeignClient 修饰的接口类 Bean 实例的工厂类
2)FeignContext 是配置组件的上下文环境,保存着相关组件的不同实例,这些实例由不同的 FeignConfiguration 配置类构造出来
3)SynchronousMethodHandler:是MethodHandler的子类,可以在 FeignClient 相应方法被调用时发送网络请求,然后再将请求响应转化为函数返回值进行输出
后面在跟踪源码的时候可以按照如下顺序来理解
动态注册(BeanDefinition)——> 实例初始化 ——> 函数调用和网络请求
1)动态注册(BeanDefinition)
OpenFeign可以通过相关配置进行多种自定义化,不通的配置会导致初始化不同的bean实例,从而控制OpenFeign调用时的具体行为,比如网络请求的编解码,压缩和日志等等。
a. FeignClientsRegistrar
所有的OpenFeign 的相关操作都是从@ EnableFeignClients 开始的。@EnableFeignClients 有三个作用: 一是引入 FeignClientsRegistrar ;二是指定扫描 Feign Client 的包信息,就是指定 Feign Client 接口类 所在的包名; 三是 指定 F eignClient 接口 的自定义配 置类。
@ EnableF eignClients 注解的定 义如下:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented

//ImportBeanDef nitionRegistrar 的子类 用于处理由FeignCl ent 注解
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    //指定自定义 feign cl ent 的自定义配置,Fe gnClientsConf guration是默认的配置类
    Class<?>[] defaultConfiguration() default {};

    // 指定被自FeignClie 修饰的类,如果不为空,那么路径自动检测机制会被关闭
    Class<?>[] clients() default {};
}
FeignClientsRegistrar是 ImportBeanDefi ni ti onRegi strar的 子类, Spring用 ImportBeanDefinitionRegistrar来 动态注册BeanDefinition。 Ope nFeign 通过F eignClientsRegistrar
来处理@F eign Client 修饰的F eignClient 类,并将这些类的 BeanDe finition注 册到 Spring 中,这样就可以使用 Auto wired 式来自动装载这些F eign Client接口类的 Bean实例。
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

...

    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        this.registerDefaultConfiguration(metadata, registry);
        this.registerFeignClients(metadata, registry);
    }

    private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        Map<String, Object> defaultAttrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
        if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
            String name;
            if (metadata.hasEnclosingClass()) {
                name = "default." + metadata.getEnclosingClassName();
            } else {
                name = "default." + metadata.getClassName();
            }

            this.registerClientConfiguration(registry, name, defaultAttrs.get("defaultConfiguration"));
        }

    }

...

}

其中,这个registerBeanDefinitions主要做了两个事情:一是注册@EnableFeignClients 提供的自定义配置类中的相关Bean实例,二是根据 @EnableFeignClients 提供的包信息扫描@FeignClient 注解修饰的 FeignClient接口类,然后进行 Bean 实例注册。

@EnableFeignClients 的自定义配置类是@Configuration 解修饰的配置类,它会提供一系列组装 FeignClient 的各种组件实例。这些组件包括:Client、Target、Decoder、Encoder和Contract 等。我们再看下registerDefaultConfiguration 的代码:
private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        //获取到metadata 中关于EnableFeignClients的属性值键值对
        Map<String, Object> defaultAttrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
        //如果EnableFeignClients 配置了defaultConfiguration 类,那么才进行下一步操作,如果没有,会使用默认的FeignConfiguration
        if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
            String name;
            if (metadata.hasEnclosingClass()) {
                name = "default." + metadata.getEnclosingClassName();
            } else {
                name = "default." + metadata.getClassName();
            }

            this.registerClientConfiguration(registry, name, defaultAttrs.get("defaultConfiguration"));
        }

    }

再看下: this.registerClientConfiguration这个方法:


 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值