OpenFeign源码解析

@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
  // 略...
}

EnableFeignClients 注解导入 FeignClientsRegistrar 来注册Feign接口

注册Feign接口

class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
  
  public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    // 注册 FeignClientSpecification 类的 BeanDefination
    // FeignClientSpecification为Feign 创建提供规范
    this.registerDefaultConfiguration(metadata, registry);
    // 注册 FeignClient
    this.registerFeignClients(metadata, registry);
  }


  public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet();
    Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
    Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
    // 判断是否有指定的 clients
    if (clients != null && clients.length != 0) {
      Class[] var12 = clients;
      int var14 = clients.length;

      for(int var16 = 0; var16 < var14; ++var16) {
        Class<?> clazz = var12[var16];
        candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
      }
    } else {
      ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
      scanner.setResourceLoader(this.resourceLoader);
      scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
      // 获取当前包路径
      Set<String> basePackages = this.getBasePackages(metadata);
      Iterator var8 = basePackages.iterator();

      while(var8.hasNext()) {
        String basePackage = (String)var8.next();
        // 找到 FeignClient 注释的类
        candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
      }
    }

    Iterator var13 = candidateComponents.iterator();

    while(var13.hasNext()) {
      BeanDefinition candidateComponent = (BeanDefinition)var13.next();
      if (candidateComponent instanceof AnnotatedBeanDefinition) {
        AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
        AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
        // 判断是否是接口类
        Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
        Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
        String name = this.getClientName(attributes);
        // 注册 FeignClient 配置类
        this.registerClientConfiguration(registry, name, attributes.get("configuration"));
        // 注册 FeignClient
        this.registerFeignClient(registry, annotationMetadata, attributes);
      }
    }

  }


  private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
    String className = annotationMetadata.getClassName();
    Class clazz = ClassUtils.resolveClassName(className, (ClassLoader)null);
    ConfigurableBeanFactory beanFactory = registry instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory)registry : null;
    String contextId = this.getContextId(beanFactory, attributes);
    String name = this.getName(attributes);
    // 定义一个FactoryBean
    FeignClientFactoryBean factoryBean = new FeignClientFactoryBean();
    factoryBean.setBeanFactory(beanFactory);
    factoryBean.setName(name);
    factoryBean.setContextId(contextId);
    factoryBean.setType(clazz);
    // 定义一个GenericBeanDefinition
    BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {
      factoryBean.setUrl(this.getUrl(beanFactory, attributes));
      factoryBean.setPath(this.getPath(beanFactory, attributes));
      factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));
      Object fallback = attributes.get("fallback");
      if (fallback != null) {
        factoryBean.setFallback(fallback instanceof Class ? (Class)fallback : ClassUtils.resolveClassName(fallback.toString(), (ClassLoader)null));
      }

      Object fallbackFactory = attributes.get("fallbackFactory");
      if (fallbackFactory != null) {
        factoryBean.setFallbackFactory(fallbackFactory instanceof Class ? (Class)fallbackFactory : ClassUtils.resolveClassName(fallbackFactory.toString(), (ClassLoader)null));
      }

      // 通过 FeignClientFactoryBean#getObject 获取到代理对象
      return factoryBean.getObject();
    });
    definition.setAutowireMode(2);
    definition.setLazyInit(true);
    this.validate(attributes);
    AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
    beanDefinition.setAttribute("factoryBeanObjectType", className);
    beanDefinition.setAttribute("feignClientsRegistrarFactoryBean", factoryBean);
    boolean primary = (Boolean)attributes.get("primary");
    beanDefinition.setPrimary(primary);
    String[] qualifiers = this.getQualifiers(attributes);
    if (ObjectUtils.isEmpty(qualifiers)) {
      qualifiers = new String[]{contextId + "FeignClient"};
    }

    // 注册GenericBeanDefinition
    BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, qualifiers);
    BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
  }

}

创建代理对象

通过FeignClientFactoryBean#getObject获取到代理对象

public class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, ApplicationContextAware, BeanFactoryAware {
  
  public Object getObject() {
    return this.getTarget();
  }


  <T> T getTarget() {
    FeignContext context = this.beanFactory != null ? (FeignContext)this.beanFactory.getBean(FeignContext.class) : (FeignContext)this.applicationContext.getBean(FeignContext.class);
    Feign.Builder builder = this.feign(context);
    // 判断Feign接口是否指定url
    if (!StringUtils.hasText(this.url)) {
      if (LOG.isInfoEnabled()) {
        LOG.info("For '" + this.name + "' URL not provided. Will try picking an instance via load-balancing.");
      }

      if (!this.name.startsWith("http")) {
        this.url = "http://" + this.name;
      } else {
        this.url = this.name;
      }

      this.url = this.url + this.cleanPath();
      return this.loadBalance(builder, context, new Target.HardCodedTarget(this.type, this.name, this.url));
    } else {
      if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
        this.url = "http://" + this.url;
      }

      String url = this.url + this.cleanPath();
      Client client = (Client)this.getOptional(context, Client.class);
      if (client != null) {
        if (client instanceof LoadBalancerFeignClient) {
          client = ((LoadBalancerFeignClient)client).getDelegate();
        }

        if (client instanceof FeignBlockingLoadBalancerClient) {
          client = ((FeignBlockingLoadBalancerClient)client).getDelegate();
        }

        if (client instanceof RetryableFeignBlockingLoadBalancerClient) {
          client = ((RetryableFeignBlockingLoadBalancerClient)client).getDelegate();
        }

        builder.client(client);
      }

      Targeter targeter = (Targeter)this.get(context, Targeter.class);
      return targeter.target(this, builder, context, new Target.HardCodedTarget(this.type, this.name, url));
    }
  }
  

  protected <T> T loadBalance(Feign.Builder builder, FeignContext context, Target.HardCodedTarget<T> target) {
    Client client = (Client)this.getOptional(context, Client.class);
    if (client != null) {
      builder.client(client);
      // DefaultTargeter
      Targeter targeter = (Targeter)this.get(context, Targeter.class);
      return targeter.target(this, builder, context, target);
    } else {
      throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon or spring-cloud-starter-loadbalancer?");
    }
  }


}
public class ReflectiveFeign extends Feign {

  public <T> T newInstance(Target<T> target) {
    // 创建方法对应的 MethodHandler,实例是 SynchronousMethodHandler
    Map<String, InvocationHandlerFactory.MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
    Map<Method, InvocationHandlerFactory.MethodHandler> methodToHandler = new LinkedHashMap();
    List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
    Method[] var5 = target.type().getMethods();
    int var6 = var5.length;

    // 遍历方法,方法和 MethodHandler 做映射
    for(int var7 = 0; var7 < var6; ++var7) {
      Method method = var5[var7];
      if (method.getDeclaringClass() != Object.class) {
        if (Util.isDefault(method)) {
          DefaultMethodHandler handler = new DefaultMethodHandler(method);
          defaultMethodHandlers.add(handler);
          methodToHandler.put(method, handler);
        } else {
          methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
        }
      }
    }

    // 创建处理器累,FeignInvocationHandler
    InvocationHandler handler = this.factory.create(target, methodToHandler);
    // 创建代理对象
    T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
    Iterator var12 = defaultMethodHandlers.iterator();

    while(var12.hasNext()) {
      DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
      defaultMethodHandler.bindTo(proxy);
    }

    return proxy;
  }

  
  static class FeignInvocationHandler implements InvocationHandler {
    
    // 处理器类的 invoke 方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      if (!"equals".equals(method.getName())) {
        // hashCode 方法
        if ("hashCode".equals(method.getName())) {
          return this.hashCode();
        } else {
          // 如果不是 toString 方法则调用 MethodHandler#invoke 方法
          return "toString".equals(method.getName()) ? this.toString() : ((InvocationHandlerFactory.MethodHandler)this.dispatch.get(method)).invoke(args);
        }
      } else {
        try {
          Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
          return this.equals(otherHandler);
        } catch (IllegalArgumentException var5) {
          return false;
        }
      }
    }
  }
  
}

执行方法

处理器 invoke 方法调用SynchronousMethodHandler#invoke方法

final class SynchronousMethodHandler implements InvocationHandlerFactory.MethodHandler {

  public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = this.buildTemplateFromArgs.create(argv);
    Request.Options options = this.findOptions(argv);
    Retryer retryer = this.retryer.clone();

    while(true) {
      try {
        return this.executeAndDecode(template, options);
      } catch (RetryableException var9) {
        // 略。。。
      }
    }
  }

  Object executeAndDecode(RequestTemplate template, Request.Options options) throws Throwable {
    Request request = this.targetRequest(template);
    if (this.logLevel != Level.NONE) {
      this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);
    }

    long start = System.nanoTime();

    Response response;
    try {
      // feign.Client.Default#execute
      // LoadBalancerFeignClient
      response = this.client.execute(request, options);
      response = response.toBuilder().request(request).requestTemplate(template).build();
    } catch (IOException var13) {
      if (this.logLevel != Level.NONE) {
        this.logger.logIOException(this.metadata.configKey(), this.logLevel, var13, this.elapsedTime(start));
      }

      throw FeignException.errorExecuting(request, var13);
    }
    
    // 略。。。
    
    }
  }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值