【OpenFeign】【源码+图解】【三】FeignClient的配置信息

【OpenFeign】【源码+图解】【二】注册OpenFeign接口的实例

4. FeignClient的配置信息

上一节中利用FeignClientFactoryBean创建@FeignClient接口的实例client,使用的时候通过**FeignClientFactoryBean.getObject()获得。本节分两步介绍:1、认识FeignClientFactoryBean ** 2、FeignClientFactoryBean.getObject()

4.1 FeignClientFactoryBean

先看下它的类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GcWQyCHO-1671541668520)(C:\Lanna\技术经验\Spring\OpenFeign\OpenFeign\2\1.png)]

先看下它的属性,它的属性基本是从**@FeignClient的属性赋值过来的,参考前面一节;再看它实现的接口,其中FactoryBean**的getObject则是分析的重点

4.2 FeignClientFactoryBean.getObject()

先看下其总体流程图

在这里插入图片描述

整个流程主要分两部分

  1. 从FeignContext获取各种beans
  2. 将beans赋值给Feign.Builder,主要是承接yml文件中feign的配置,或者@FeignClient.configuration的配置,或者@EnableFeignClients.defaultConfiguration
  3. 通过工具类Targeter类创建instance

接下来我们逐一分析

4.2.1 FeignContext

在这里插入图片描述

如果看过前面关于LoadBalance的3.2节文章就会了解NamedContextFactory,这里不再详细分析。

对于FeignContext它是在Spring启动的时候通过FeignAutoConfiguration注入容器的
看下FeignAutoConfiguration

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Feign.class)
@EnableConfigurationProperties({ 
    FeignClientProperties.class,  // yml文件中feign.client.*的配置
    FeignHttpClientProperties.class, // yml文件中feign.httpclient.*的配置
	FeignEncoderProperties.class }) // yml文件中feign.encoder.*的配置
public class FeignAutoConfiguration {
    @Autowired(required = false)
    // configurations即@EnableFeignClients.defaultConfiguration和@FeignClient.configuration,参考FeignClientsRegistrar的流程图
	private List<FeignClientSpecification> configurations = new ArrayList<>();

	@Bean
	public FeignContext feignContext() {
		FeignContext context = new FeignContext();
        // 设置configurations
		context.setConfigurations(this.configurations);
		return context;
	}
}

FeignClientFactoryBean.getObject()方法中使用了大量的getInstance(String contextName, String beanName, Class<T> type)方法,过程不再详述(参考LoadBalance的3.2节),大致过程是:

  1. 首次根据configurations创建名为contextName的ApplicationContext,并存放到FeignContext,之后直接取用
  2. 从ApplicationContext获取beanName的bean

FeignClientFactoryBean.getObject()主要是获取了以下的类:

  1. Feign.Builder
  2. Client
  3. FeignBuilderCustomizer
  4. Targeter
  5. FeignClientConfigurer
  6. FeignLoggerFactory
  7. Encoder(SpringEncoder)
  8. Decoder(OptionalDecoder)
  9. Contract(SpringMvcContract)
  10. Request.Options
  11. Logger.Level
  12. Retryer
  13. ErrorDecoder
  14. FeignErrorDecoderFactory
  15. RequestInterceptor
  16. QueryMapEncoder
  17. ExceptionPropagationPolicy
  18. Capability

这些类可以自配置

4.2.2 Feign.Builder

先看下它的类图
在这里插入图片描述

FeignClientFactoryBean.getObject()中对Feign.Builder赋值结束后默认的值如下

在这里插入图片描述

对于Builder里面的类,如RequestInterceptor等的默认配置是通过下列Configuration注入的

在这里插入图片描述

当然,也可以自己配置,实现相应的接口,然后通过yml文件配置,如下图

在这里插入图片描述

4.2.2.1 Bean的配置方式

Contract为例,三种方式:YML、@FeignClient.configuration、@EnableFeignClients.defaultConfiguration

YML

在这里插入图片描述

@FeignClient.configuration
  1. 实现接口

    public class MyContract implements Contract {
        @Override
        public List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {
            return new ArrayList<>();
        }
    }
    
  2. 添加配置文件

    public class MyConfiguration {
        @Bean
        @Primary
        MyContract myContract() {
            return new MyContract();
        }
    }
    
  3. 添加到@FeignClient

    @FeignClient(value = "product", configuration = MyConfiguration.class)
    public interface ProductFeignClient{
    }
    
@EnableFeignClients.defaultConfiguration
  1. 实现接口

    public class MyDefaultContract implements Contract {
        @Override
        public List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {
            return new ArrayList<>();
        }
    }
    
  2. 添加配置文件

    public class MyDefaultConfiguration {
    
        @Bean
        MyDefaultContract defaultContract() {
            return new MyDefaultContract();
        }
    }
    
  3. 添加到@FeignClient

    @SpringBootApplication
    @EnableFeignClients(defaultConfiguration = MyDefaultConfiguration.class)
    public class FeignClientApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(FeignClientApplication.class, args);
    	}
    }
    

注意

  1. 注入的顺序:YML > @FeignClient.configuration , @EnableFeignClients.defaultConfiguration
  2. @FeignClient.configuration与@EnableFeignClients.defaultConfiguration同时使用时要注明谁是Primary,否则会报错

Targeter

先看下Targeter的类图,了解下功能

在这里插入图片描述

Targeter的作用主要是中转站,默认实现是DefaultTargeter,先看下FeignClientFactoryBean.getObject()中的源码调用

public class FeignClientFactoryBean
		implements FactoryBean<Object>, InitializingBean, ApplicationContextAware, BeanFactoryAware {
    @Override
	public Object getObject() {
        // 1
		return getTarget();
	}
    
    <T> T getTarget() {
        ......
        if (!StringUtils.hasText(url)) {
            ......
            // 2
			return (T) loadBalance(builder, context, new HardCodedTarget<>(type, name, url));
		}
    }
    
    protected <T> T loadBalance(Feign.Builder builder, FeignContext context, HardCodedTarget<T> target) {
		Client client = getOptional(context, Client.class);
		if (client != null) {
			builder.client(client);
			applyBuildCustomizers(context, builder);
            // 获取Targeter实例,默认DefaultTargeter
			Targeter targeter = get(context, Targeter.class);
            // 这里的target为HardCodedTarget
            // 3 下一章节的入口
			return targeter.target(this, builder, context, target);
		}
        ......
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值