openFeign的实现的过程_Feign详细构建过程及自定义扩展

5b3bf5bb4dcb9789aecbf78ed3054280.png

探究清楚 feign 的原理,自定义 feign 功能

spring-cloud-openfeign-core-2.1.1.RELEASE.jarHystrixFeign 的详细构建过程:

@EnableFeignClients -> FeignClientsRegistrar 扫描 @Feign注解的类 -> FeignClientFactoryBean通过Targeter生产FeignClient -> Targeter通过Feign.Builder构建Feign -> Feign.Builder

1. 准备工作(配置)

  1. FeignAutoConfiguration自动配置类
 @Configuration @ConditionalOnClass(name = "feign.hystrix.HystrixFeign") protected static class HystrixFeignTargeterConfiguration { @Bean @ConditionalOnMissingBean public Targeter feignTargeter() { return new HystrixTargeter(); } } @Configuration @ConditionalOnMissingClass("feign.hystrix.HystrixFeign") protected static class DefaultFeignTargeterConfiguration { @Bean @ConditionalOnMissingBean public Targeter feignTargeter() { return new DefaultTargeter(); } }
  1. feign.hystrix.HystrixFeign类存在时,将 HystrixTargeter 注册为 Targeter 类型的 bean
  2. feign.hystrix.HystrixFeign类不存在时,使用 DefaultTargeter 。
  3. 看起来似乎可以使用自定义的Targeter代替Hystrix或默认的,这样就可以自定义各种功能了。实际上不行,因为 Targeter 是 package 访问级别的。
  4. FeignClientsConfiguration
@Configurationpublic class FeignClientsConfiguration {   @Bean @ConditionalOnMissingBean public Retryer feignRetryer() { return Retryer.NEVER_RETRY; } @Bean @Scope("prototype") @ConditionalOnMissingBean public Feign.Builder feignBuilder(Retryer retryer) { return Feign.builder().retryer(retryer); }  @Configuration @ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class }) protected static class HystrixFeignConfiguration { @Bean @Scope("prototype") @ConditionalOnMissingBean @ConditionalOnProperty(name = "feign.hystrix.enabled") public Feign.Builder feignHystrixBuilder() { return HystrixFeign.builder(); } }}

重要Feign 以及内部类 Feign.Builder 都是 public 访问级别,可以注入自定义的bean。

2.EnableFeignClients与FeignClientsRegistrar类

将使用@FeignClient注解的类注册成spring bean,并使用注解中的配置

  1. 在@EnableFeignClients注解中导入FeignClientsRegistrar类
  2. FeignClientsRegistrar类实现了ImportBeanDefinitionRegistrar类,会由spring框架执行实现方法 registerBeanDefinitions(AnnotationMetaData, BeanDefinitionRegistry)
  3. FeignClientsRegistrar中的 registerBeanDefinitions方法调用两个方法
  4. registerDefaultConfiguration:注册默认的配置
  5. registerFeignClients:注册Feign客户端(重点)
  6. registerFeignClients:获取 @EnableFeignClients注解中定义的配置扫描feign客户端
  7. registerFeignClients:通过registerFeignClient(BeanDefinitionRegistry, AnnotationMetadata, Map)方法注册每一个feignClient,过程:先获取 @FeignClient注解中定义的配置,将配置应用在spring bean 工厂 FeignClientFactoryBean, 通过工厂类 FeignClientFactoryBean 为每一个使用@FeignClient注解的类生产 FeignClient,详细过程见下一节

3.FeignClientFactoryBean

FeignClient工厂bean。

class FeignClientFactoryBean implements FactoryBean, InitializingBean, ApplicationContextAware{ //...}

通过实现方法 FactoryBean#getObject()来由spring框架生产FeignClient。

@Overridepublic Object getObject() throws Exception { return getTarget();}/** * 获得目标 * 1. 获得FeignContext * 2. 从FeignContext中获得Feign构建器Feign.Builder * 3. 从FeignContext中获得Client,判断是否进行负载均衡 * 4. 从FeignContext中获得Target,并执行Target的默认方法target(FeignClientFactoryBean, Feign.Builder, FeignContext, Target.HardCodedTarget); * 5.由于一开始注入的Feign.Builder是HystrixFeign.Builder,则此处是调用HystrixFeign.Builder里的对应方法 */ T getTarget() { FeignContext context = this.applicationContext.getBean(FeignContext.class); Feign.Builder builder = feign(context); //省略部分代码 // ...... Client client = getOptional(context, Client.class); if (client != null) { if (client instanceof LoadBalancerFeignClient) { // not load balancing because we have a url, // but ribbon is on the classpath, so unwrap client = ((LoadBalancerFeignClient) client).getDelegate(); } builder.client(client); } Targeter targeter = get(context, Targeter.class); return (T) targeter.target(this, builder, context, new HardCodedTarget<>(this.type, this.name, url));} protected Feign.Builder feign(FeignContext context) { FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class); Logger logger = loggerFactory.create(this.type); // @formatter:off Feign.Builder builder = get(context, Feign.Builder.class) // required values .logger(logger) .encoder(get(context, Encoder.class)) .decoder(get(context, Decoder.class)) .contract(get(context, Contract.class)); // @formatter:on configureFeign(context, builder); return builder; }

工厂获得对象(目标):

1. 获得FeignContext(feign上下文)

2. 从FeignContext中获得Feign构建器Feign.Builder(public,可以在此使用自定义构建器)

3. 从FeignContext中获得Client,判断是否进行负载均衡

4. 从FeignContext中获得Target,并执行Target的默认方法target(FeignClientFactoryBean, Feign.Builder,

FeignContext, Target.HardCodedTarget);

5. 由于一开始注入的 *Targeter* 是 *HystrixTargeter* ,则此处是调用 HystrixTargeter 里的对应方法(从第一节的配置来看,只要 *feign.hystrix.HystrixFeign* 类存在,就是注入的 *HystrixTargeter *, 否则是 *DefaultTargeter*,对于需要**自定义构建feign的,这里不太重要**)

4.Targeter

4.1.HystrixTargeter

class HystrixTargeter implements Targeter { @Override public  T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context, Target.HardCodedTarget target) { // 若不是 HystrixFeign,则执行其对应的默认target方法。 // 此处只处理HystrixFeign。 if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) { return feign.target(target); } feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign; SetterFactory setterFactory = getOptional(factory.getName(), context, SetterFactory.class); if (setterFactory != null) { builder.setterFactory(setterFactory); } Class> fallback = factory.getFallback(); if (fallback != void.class) { return targetWithFallback(factory.getName(), context, target, builder, fallback); } Class> fallbackFactory = factory.getFallbackFactory(); if (fallbackFactory != void.class) { return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory); } // 调用从Feign.Builder继承的方法。 return feign.target(target); }  private  T targetWithFallbackFactory(String feignClientName, FeignContext context, Target.HardCodedTarget target, HystrixFeign.Builder builder, Class> fallbackFactoryClass) { FallbackFactory extends T> fallbackFactory = (FallbackFactory extends T>) getFromContext( "fallbackFactory
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值