Spring Cloud Feign源码解析

咱们知道要使用feign,须要在springboot启动类放入@EnableFeignClients开关来打开feign的使用。java

@EnableFeignClients
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplication {

   public static void main(String[] args) {
      SpringApplication.run(GatewayApplication.class, args);
   }

}

而后会使用例如spring

@FeignClient("user-center")
public interface UserClient {
    @PostMapping("/users-anon/finduser")
    LoginAppUser findUserByName(@RequestParam("username") String username);
}

如今咱们能够考虑的方向是打上了@FeignClient("user-center")标签后,UserClient接口是如何被实例化成对象的,而后是在Controller中调用UserClient对象是如何进行网络请求的。数组

@Slf4j
@RestController
public class TokenController {

    @Autowired
    private Oauth2Client oauth2Client;
    @Autowired
    private UserClient userClient;


    /**
     * 系统登录<br>
     * 根据用户名登陆<br>
     * 采用oauth2密码模式获取access_token和refresh_token
     *
     * @param username
     * @param password
     * @return
     */
    @SuppressWarnings("unchecked")
    @PostMapping("/sys/login")
    public Result<Map> login(@RequestParam String username,@RequestParam String password) {
        Map<String, String> parameters = new HashMap<>();
        parameters.put(OAuth2Utils.GRANT_TYPE, "password");
        parameters.put(OAuth2Utils.CLIENT_ID, "system");
        parameters.put("client_secret", "system");
        parameters.put(OAuth2Utils.SCOPE, "app");
//    parameters.put("username", username);
        // 为了支持多类型登陆,这里在username后拼装上登陆类型
        parameters.put("username", username + "|" + CredentialType.USERNAME.name());
        parameters.put("password", password);

        Map<String, Object> tokenInfo = oauth2Client.postAccessToken(parameters);
        AppUser user = userClient.findUserByName(username);
        tokenInfo.put("user",user);
        saveLoginLog(username, "用户名密码登录");

        return Result.success(tokenInfo);
    }

在feign的框架源码中,有3个类是比较重要的,FeignClientFactoryBean,FeignContext,SynchronousMethodHandler.springboot

咱们先来看一下@EnableFeignClients的做用。网络

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)  //用于处理@FeignClient注解
public @interface EnableFeignClients {
   //如下这三个都是用于指定须要扫描的包
   String[] value() default {};
   String[] basePackages() default {};
   Class<?>[] basePackageClasses() default {};
   //用于自定义feign client的自定义配置,能够配置Decoder(解码器),Encoder(编码器)和Contract等组件,    //FeignClientsConfiguration是默认的配置类
   Class<?>[] defaultConfiguration() default {};
   //指定被@FeignClient修饰的类,若是不为空,那么路径自动检测机制会被关闭
   Class<?>[] clients() default {};
}

@Import注解有四个做用app

  1. 声明一个bean
  2. 导入@Configuration注解的配置类
  3. 导入ImportSelector的实现类
  4. 导入ImportBeanDefinitionRegistrar的实现类

FeignClientsRegistrar是用来处理@FeignClient修饰的FeignClient接口类,将这些接口类的BeanDefinition注册到Spring容器中,这样就可使用@Autowired等方式来自动装载这些@FeignClient接口类的Bean实例。框架

class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
      ResourceLoaderAware, EnvironmentAware

FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口,该接口是Spring实现bean动态注入的。咱们来看一下该接口的方法ide

public void registerBeanDefinitions(
      AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);

在FeignClientsRegistrar中的实现微服务

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
   //从EnableFeignClients的属性值来构建Feign的自定义Configuration进行注册
   registerDefaultConfiguration(metadata, registry);
   //扫描package,注册被@FeignClient修饰的接口类的Bean信息
   registerFeignClients(metadata, registry);
}
private void registerDefaultConfiguration(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
   //将@EnableFeignClients的全部属性值导入map中
   Map<String, Object> defaultAttrs = metadata
         .getAnnotationAttributes(EnableFeignClients.class.getName(), true);
   //若是@EnableFeignClients配置了defaultConfiguration,则往下运行。若是没有,rantion
   //会使用默认的FeignConfiguration,通常咱们这里不会设置这些配置,都是默认,可是若是设置了,
   //就会比如咱们本身写了@Configuration的类同样的效果,这里是自动配置了
   if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
      String name;
      //若是原始类中有内部类,获取内部类名
      if (metadata.hasEnclosingClass()) {
         name = "default." + metadata.getEnclosingClassName();
      }
      //不然获取原始类名
      else {
         name = "default." + metadata.getClassName();
      }
      //注册@EnableFeignClients的Configuration配置
      registerClientConfiguration(registry, name,
            defaultAttrs.get("defaultConfiguration"));
   }
}
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
      Object configuration) {
   //获取一个FeignClientSpecification的建造器
   BeanDefinitionBuilder builder = BeanDefinitionBuilder
         .genericBeanDefinition(FeignClientSpecification.class);
   //传入构造参数
   builder.addConstructorArgValue(name);
   builder.addConstructorArgValue(configuration);
   //将FeignClientSpecification当成内部类对象进行注册
   registry.registerBeanDefinition(
         name + "." + FeignClientSpecification.class.getSimpleName(),
         builder.getBeanDefinition());
}

以上这里能够方便咱们学习怎么写一个标签达到自动配置效果。如下是扫描包,并把打了@FeignClient标签的接口给加载到Spring容器中。post

public void registerFeignClients(AnnotationMetadata metadata,
      BeanDefinitionRegistry registry) {
   //获取扫描器
   ClassPathScanningCandidateComponentProvider scanner = getScanner();
   scanner.setResourceLoader(this.resourceLoader);

   Set<String> basePackages;
   //将@EnableFeignClients的全部自定义配置属性放入内存map中
   Map<String, Object> attrs = metadata
         .getAnnotationAttributes(EnableFeignClients.class.getName());
   //初始化一个@FeignClient的标签类型过滤器
   AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
         FeignClient.class);
   //若是设置了@EnableFeignClients的自定义配置,获取clients配置项中的Class数组
   final Class<?>[] clients = attrs == null ? null
         : (Class<?>[]) attrs.get("clients");
   //若是没有自定义配置
   if (clients == null || clients.length == 0) {
      //扫描器添加标签过滤类型
      scanner.addIncludeFilter(annotationTypeFilter);
      //获取默认配置扫描包集合
      basePackages = getBasePackages(metadata);
   }
   else { //若是有自定义配置
      final Set<String> clientClasses = new HashSet<>();
      basePackages = new HashSet<>();
      //遍历配置的每个client Class
      for (Class<?> clazz : clients) {
         //添加每个client Class的包
         basePackages.add(ClassUtils.getPackageName(clazz));
         //添加每个client Class的类名(包含内部类名)
         clientClasses.add(clazz.getCanonicalName());
      }
      //初始化一个内部类过滤器
      AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
         @Override
         protected boolean match(ClassMetadata metadata) {
            String cleaned = metadata.getClassName().replaceAll("\\$", ".");
            return clientClasses.contains(cleaned);
         }
      };
      //扫描器添加过滤设置
      scanner.addIncludeFilter(
            new AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));
   }
   //遍历扫描包集合
   for (String basePackage : basePackages) {
      //用扫描器扫描包,获取bean集合
      Set<BeanDefinition> candidateComponents = scanner
            .findCandidateComponents(basePackage);
      //遍历扫描到的bean集合
      for (BeanDefinition candidateComponent : candidateComponents) {
         //若是该bean为一个标签订义的bean
         if (candidateComponent instanceof AnnotatedBeanDefinition) {
            // verify annotated class is an interface
            AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
            //获取该bean的元数据
            AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
            //断言该bean为一个接口(Interface)
            Assert.isTrue(annotationMetadata.isInterface(),
                  "@FeignClient can only be specified on an interface");
            //获取@FeignClient的全部属性放入map中
            Map<String, Object> attributes = annotationMetadata
                  .getAnnotationAttributes(
                        FeignClient.class.getCanonicalName());
            //获取@FeignClient配置的name(name或者value或者serviceId必须配置一个,并取其一)
            String name = getClientName(attributes);
            //注册单个@FeignClient的Configuration配置
            registerClientConfiguration(registry, name,
                  attributes.get("configuration"));
            //注册@FeignClient定义的bean
            registerFeignClient(registry, annotationMetadata, attributes);
         }
      }
   }
}

这里咱们须要看一下@FeignClient标签有哪些属性

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {

   /**
    * name:指定FeignClient的名称,若是项目使用了Ribbon,name属性会做为微服务的名称,用于服务发现
    */
   @AliasFor("name")
   String value() default "";

   /**
    * name:指定FeignClient的名称,若是项目使用了Ribbon,name属性会做为微服务的名称,用于服务发现
    */
   @Deprecated
   String serviceId() default "";

   /**
    * name:指定FeignClient的名称,若是项目使用了Ribbon,name属性会做为微服务的名称,用于服务发现
    */
   @AliasFor("value")
   String name() default "";
   
   /**
    * 限定符
    */
   String qualifier() default "";

   /**
    * url通常用于调试,能够手动指定@FeignClient调用的地址
    */
   String url() default "";

   /**
    * 当发生http 404错误时,若是该字段位true,会调用decoder进行解码,不然抛出FeignException
    */
   boolean decode404() default false;

   /**
    * Feign配置类,能够自定义Feign的Encoder、Decoder、LogLevel、Contract
    */
   Class<?>[] configuration() default {};

   /**
    * 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
    */
   Class<?> fallback() default void.class;

   /**
    * 工厂类,用于生成fallback类示例,经过这个属性咱们能够实现每一个接口通用的容错逻辑,减小重复的代码
    */
   Class<?> fallbackFactory() default void.class;

   /**
    * 定义当前FeignClient的统一前缀
    */
   String path() default "";

   /**
    * 标记feign代理为主bean
    */
   boolean primary() default true;

}
private String getClientName(Map<String, Object> client) {
   if (client == null) {
      return null;
   }
   //获取@FeignClient配置的value
   String value = (String) client.get("value");
   if (!StringUtils.hasText(value)) {
      //若是value为空,获取@FeignClient配置的name
      value = (String) client.get("name");
   }
   if (!StringUtils.hasText(value)) {
      //若是value为空,获取@FeignClient配置的serviceId
      value = (String) client.get("serviceId");
   }
   //若是value不为空,返回value
   if (StringUtils.hasText(value)) {
      return value;
   }

   throw new IllegalStateException("Either 'name' or 'value' must be provided in @"
         + FeignClient.class.getSimpleName());
}
private void registerFeignClient(BeanDefinitionRegistry registry,
      AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
   //获取被@FeignClient标签注解的类名称,这里是接口名
   String className = annotationMetadata.getClassName();
   //设置bean建造器的bean工厂
   BeanDefinitionBuilder definition = BeanDefinitionBuilder
         .genericBeanDefinition(FeignClientFactoryBean.class);
   //断言@FeignClient配置的fallback,fallbackFactory必须为接口
   validate(attributes);
   //建造器添加@FeignClient各配置属性
   definition.addPropertyValue("url", getUrl(attributes));
   definition.addPropertyValue("path", getPath(attributes));
   String name = getName(attributes);
   definition.addPropertyValue("name", name);
   definition.addPropertyValue("type", className);
   definition.addPropertyValue("decode404", attributes.get("decode404"));
   definition.addPropertyValue("fallback", attributes.get("fallback"));
   definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
   definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);

   String alias = name + "FeignClient";
   //使用该建造器建造bean
   AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
   //获取主bean标识
   boolean primary = (Boolean)attributes.get("primary"); // has a default, won't be null
   //设置该bean是否为主bean
   beanDefinition.setPrimary(primary);
   //经过@FeignClient设置的限定符属性获取别名
   String qualifier = getQualifier(attributes);
   if (StringUtils.hasText(qualifier)) {
      alias = qualifier;
   }
   //初始化一个bean的类名、别名解析器
   BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
         new String[] { alias });
   //经过bean工厂和别名解析器,将该bean注册到spring容器中
   BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
private void validate(Map<String, Object> attributes) {
   AnnotationAttributes annotation = AnnotationAttributes.fromMap(attributes);
   // This blows up if an aliased property is overspecified
   // FIXME annotation.getAliasedString("name", FeignClient.class, null);
   Assert.isTrue(
      !annotation.getClass("fallback").isInterface(),
      "Fallback class must implement the interface annotated by @FeignClient"
   );
   Assert.isTrue(
      !annotation.getClass("fallbackFactory").isInterface(),
      "Fallback factory must produce instances of fallback classes that implement the interface annotated by @FeignClient"
   );
}

咱们在这里看到了FeignClientFactoryBean的工厂类,它的做用就是实例化bean的,因为咱们的bean是接口,要实例化成对象,咱们须要来看一下它的getObject()方法。

@Override
public Object getObject() throws Exception {
   //在Spring容器中拿取FeignContext对象bean
   FeignContext context = applicationContext.getBean(FeignContext.class);
   //从feignContext上下文中获取Feign的建造器
   Feign.Builder builder = feign(context);
   //若是在@FeignClient中未设置url属性
   if (!StringUtils.hasText(this.url)) {
      String url;
      //若是@FeignClient的name属性以"http"开头
      if (!this.name.startsWith("http")) {
         //设置url的值为http://name
         url = "http://" + this.name;
      }
      else {
         //不然设置url为name
         url = this.name;
      }
      
      url += cleanPath();
      return loadBalance(builder, context, new HardCodedTarget<>(this.type,
            this.name, url));
   }
   if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
      this.url = "http://" + this.url;
   }
   String url = this.url + cleanPath();
   Client client = getOptional(context, Client.class);
   if (client != null) {
      if (client instanceof LoadBalancerFeignClient) {
         // not lod 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 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);

   //从上下文中获取Feign的建造器bean实例builder
   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;
}
protected void configureFeign(FeignContext context, Feign.Builder builder) {
   FeignClientProperties properties = applicationContext.getBean(FeignClientProperties.class);
   if (properties != null) {
      if (properties.isDefaultToProperties()) {
         configureUsingConfiguration(context, builder);
         configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
         configureUsingProperties(properties.getConfig().get(this.name), builder);
      } else {
         configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()), builder);
         configureUsingProperties(properties.getConfig().get(this.name), builder);
         configureUsingConfiguration(context, builder);
      }
   } else {
      configureUsingConfiguration(context, builder);
   }
}
protected void configureUsingConfiguration(FeignContext context, Feign.Builder builder) {
   Logger.Level level = getOptional(context, Logger.Level.class);
   if (level != null) {
      builder.logLevel(level);
   }
   Retryer retryer = getOptional(context, Retryer.class);
   if (retryer != null) {
      builder.retryer(retryer);
   }
   ErrorDecoder errorDecoder = getOptional(context, ErrorDecoder.class);
   if (errorDecoder != null) {
      builder.errorDecoder(errorDecoder);
   }
   Request.Options options = getOptional(context, Request.Options.class);
   if (options != null) {
      builder.options(options);
   }
   Map<String, RequestInterceptor> requestInterceptors = context.getInstances(
         this.name, RequestInterceptor.class);
   if (requestInterceptors != null) {
      builder.requestInterceptors(requestInterceptors.values());
   }

   if (decode404) {
      builder.decode404();
   }
}
protected <T> T getOptional(FeignContext context, Class<T> type) {
   return context.getInstance(this.name, type);
}
protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
      HardCodedTarget<T> target) {
   //Client是一个进行Http请求的类,为后续的第二个问题打下伏笔
   Client client = getOptional(context, Client.class);
   if (client != null) {
      //建造器拼装client对象
      builder.client(client);
      //从自己名称的上下文中获取Targeter的bean实例,这里Targeter是一个接口
      //它有两个实现类DefaultTargeter,HystrixTargeter
      //这里进行了分岔,看上下文中注册的是使用默认的Targeter仍是熔断器的Targeter
      Targeter targeter = get(context, Targeter.class);
      //根据上下文中不一样的注册调用不一样对象的target方法,这里咱们具体看DefaultTargeter的方法
      return targeter.target(this, builder, context, target);
   }

   throw new IllegalStateException(
         "No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
}
interface Targeter {
   <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
             Target.HardCodedTarget<T> target);
}
class DefaultTargeter implements Targeter {

   @Override
   public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
                  Target.HardCodedTarget<T> target) {
      //直接调用Feign建造器的方法
      return feign.target(target);
   }
}

在Feign中

public <T> T target(Target<T> target) {
  return build().newInstance(target);
}

因为Feign是一个抽象类,这个newInstance为一个抽象方法

public abstract <T> T newInstance(Target<T> target);

在ReflectiveFeign中,ReflectiveFeign为Feign的子类,能够说前面全部的铺垫就是为了这个方法。

@SuppressWarnings("unchecked")
@Override
public <T> T newInstance(Target<T> target) { //Target是一个接口,咱们这里传入的是它的内部实现类HardCodedTarget
  //获取目标的方法的方法名和方法处理器映射
  Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
  Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
  List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
  //遍历目标type(被@FeignClinet注解的接口)的全部方法
  for (Method method : target.type().getMethods()) {
    if (method.getDeclaringClass() == Object.class) {
      //若是目标type为Object,跳到下一个method,这里是说方法不来自普通类的顶层父类Object,按道理目标type(Class)不会为普通类,只是接口
      continue;
    } else if(Util.isDefault(method)) { //若是该方法为接口默认方法,即被default修饰的方法
      //初始化一个默认方法处理器对象
      DefaultMethodHandler handler = new DefaultMethodHandler(method);
      //将该处理器对象添加到defaultMethodHandlers列表中
      defaultMethodHandlers.add(handler);
      //将该处理器对象添加到methodToHandler映射中
      methodToHandler.put(method, handler);
    } else {
      //若是不是默认方法,从nameToHandler中取出方法处理器并放入methodToHandler映射中
      methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
    }
  }
  //使用工厂建立一个代理处理器对象
  InvocationHandler handler = factory.create(target, methodToHandler);
  //
  T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);

  for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
    defaultMethodHandler.bindTo(proxy);
  }
  return proxy;
}
//MethodMetadata各属性
private String configKey;
private transient Type returnType;
private Integer urlIndex;
private Integer bodyIndex;
private Integer headerMapIndex;
private Integer queryMapIndex;
private boolean queryMapEncoded;
private transient Type bodyType;
private RequestTemplate template = new RequestTemplate();
private List<String> formParams = new ArrayList<String>();
private Map<Integer, Collection<String>> indexToName =
    new LinkedHashMap<Integer, Collection<String>>();
private Map<Integer, Class<? extends Expander>> indexToExpanderClass =
    new LinkedHashMap<Integer, Class<? extends Expander>>();
private Map<Integer, Boolean> indexToEncoded = new LinkedHashMap<Integer, Boolean>();
private transient Map<Integer, Expander> indexToExpander;
private final SynchronousMethodHandler.Factory factory; //同步方法处理器工厂
public Map<String, MethodHandler> apply(Target key) {
  //获取目标对象的type(Class类)属性的方法元数据列表
  //这里的type其实就是被@FeignClient注解的接口,而接口的方法就是相似诸如  
  //@PostMapping("/users-anon/finduser") 
  //LoginAppUser findUserByName(@RequestParam("username") String username);
  List<MethodMetadata> metadata = contract.parseAndValidatateMetadata(key.type());
  Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>();
  //遍历全部的方法元数据
  for (MethodMetadata md : metadata) {
    BuildTemplateByResolvingArgs buildTemplate;
    //若是方法参数为@RequestParam,不为@RequestBody
    if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {
      //构造一个BuildFormEncodedTemplateFromArgs对象,BuildFormEncodedTemplateFromArgs是BuildTemplateByResolvingArgs的子类
      buildTemplate = new BuildFormEncodedTemplateFromArgs(md, encoder);
    } else if (md.bodyIndex() != null) {
      //若是方法参数为@RequestBody,构造BuildEncodedTemplateFromArgs对象,BuildEncodedTemplateFromArgs也为BuildTemplateByResolvingArgs的子类
      buildTemplate = new BuildEncodedTemplateFromArgs(md, encoder);
    } else {
      //若是没有参数,构造BuildTemplateByResolvingArgs对象
      buildTemplate = new BuildTemplateByResolvingArgs(md);
    }
    //建立一个方法处理器,并放入到方法配置映射中
    result.put(md.configKey(),
               factory.create(key, md, buildTemplate, options, decoder, errorDecoder));
  }
  return result;
}
public MethodHandler create(Target<?> target, MethodMetadata md,
                            RequestTemplate.Factory buildTemplateFromArgs,
                            Options options, Decoder decoder, ErrorDecoder errorDecoder) {
  return new SynchronousMethodHandler(target, client, retryer, requestInterceptors, logger,
                                      logLevel, md, buildTemplateFromArgs, options, decoder,
                                      errorDecoder, decode404);
}
public static String configKey(Class targetType, Method method) {
  StringBuilder builder = new StringBuilder();
  //拼装类名+“#”+方法名+“(”
  builder.append(targetType.getSimpleName());
  builder.append('#').append(method.getName()).append('(');
  //遍历方法的参数类型
  for (Type param : method.getGenericParameterTypes()) {
    //根据参数类型的全部可能进行处理,获取处理结果的类型
    param = Types.resolve(targetType, targetType, param);
    //拼接该类型的类名称
    builder.append(Types.getRawType(param).getSimpleName()).append(',');
  }
  //若是方法有参数
  if (method.getParameterTypes().length > 0) {
    //移除最末尾的字符
    builder.deleteCharAt(builder.length() - 1);
  }
  //移除后拼装),而后返回
  return builder.append(')').toString();
}
static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
  // This implementation is made a little more complicated in an attempt to avoid object-creation.
  while (true) {
    //若是参数类型为泛型
    if (toResolve instanceof TypeVariable) {
      //强制转化为泛型
      TypeVariable<?> typeVariable = (TypeVariable<?>) toResolve;
      //获取泛型的类型
      toResolve = resolveTypeVariable(context, contextRawType, typeVariable);
      if (toResolve == typeVariable) {
        //返回该泛型的类型
        return toResolve;
      }

    } else if (toResolve instanceof Class && ((Class<?>) toResolve).isArray()) {
      //若是参数类型为数组,将参数类型转化为类
      Class<?> original = (Class<?>) toResolve;
      //获取数组的原类型,数组的原类型若是不是多维数组就不可能仍是数组
      Type componentType = original.getComponentType();
      //递归调用,获取新的类型
      Type newComponentType = resolve(context, contextRawType, componentType);
      //若是新类型为数组原类型,返回原参数类型的类(数组类型),不然返回封装了新类型的泛型数组类型对象,该对象的类实现
      //泛型数组类型接口
      return componentType == newComponentType ? original : new GenericArrayTypeImpl(
          newComponentType);

    } else if (toResolve instanceof GenericArrayType) { //若是参数类型为泛型数组类型
      GenericArrayType original = (GenericArrayType) toResolve;
      //获取该泛型
      Type componentType = original.getGenericComponentType();
      //递归调用,获取新类型
      Type newComponentType = resolve(context, contextRawType, componentType);
      //若是新类型就为该泛型,返回原参数类型(转化为泛型数组类型),不然返回封装了新类型的泛型数组类型对象,该对象的类实现
     //泛型数组类型接口
      return componentType == newComponentType ? original : new GenericArrayTypeImpl(
          newComponentType);

    } else if (toResolve instanceof ParameterizedType) { //若是参数类型为参数化类型
      ParameterizedType original = (ParameterizedType) toResolve;
      //获取该参数化类型的外部类
      Type ownerType = original.getOwnerType();
      //递归调用获取新外部类型
      Type newOwnerType = resolve(context, contextRawType, ownerType);
      //判断新外部类型与原外部类型是否不一样
      boolean changed = newOwnerType != ownerType;
      //获取参数化类型的全部参数类型
      Type[] args = original.getActualTypeArguments();
      //遍历全部参数类型
      for (int t = 0, length = args.length; t < length; t++) {
        //递归调用每个参数类型获取对应的新的类型
        Type resolvedTypeArgument = resolve(context, contextRawType, args[t]);
        //若是对应的新类型不一样于原参数类型
        if (resolvedTypeArgument != args[t]) {
          //若是新外部类型为原外部类型
          if (!changed) {
            //克隆新内存地址
            args = args.clone();
            //设定新外部类型与原外部类型不一样
            changed = true;
          }
          //将新类型放入原参数类型数组中
          args[t] = resolvedTypeArgument;
        }
      }
      //若是新外部类型与原外部类型不一样,返回封装了新外部类型和原内部类以及参数化多参数数组的参数化类型对象
      //不然返回原参数化类型
      return changed
             ? new ParameterizedTypeImpl(newOwnerType, original.getRawType(), args)
             : original;

    } else if (toResolve instanceof WildcardType) { //若是参数类型为通配符表达式类型,通配符表达式类型例如<? extends String>、<? super String>
      WildcardType original = (WildcardType) toResolve;
      //获取通配符前类型数组
      Type[] originalLowerBound = original.getLowerBounds();
      //获取通配符后类型数组
      Type[] originalUpperBound = original.getUpperBounds();
      //若是通配符下界类型能够获取
      if (originalLowerBound.length == 1) {
        //递归调用,获取新下界类型
        Type lowerBound = resolve(context, contextRawType, originalLowerBound[0]);
        //若是新下界类型与原下界不一样
        if (lowerBound != originalLowerBound[0]) {
          //返回封装了以Object.class为上界类型,新下界类型为下界类型的通配符类型对象
          return new WildcardTypeImpl(new Type[]{Object.class}, new Type[]{lowerBound});
        }
      } else if (originalUpperBound.length == 1) { //若是通配符上界类型能够获取
        //递归调用,获取新上界类型
        Type upperBound = resolve(context, contextRawType, originalUpperBound[0]);
        //若是新上界类型与原上界类型不一样
        if (upperBound != originalUpperBound[0]) {
          //返回封装了以新上界类型为上界类型,空为下界类型的通配符类型对象
          return new WildcardTypeImpl(new Type[]{upperBound}, EMPTY_TYPE_ARRAY);
        }
      }
      //若是以上都没有,返回原类型
      return original;

    } else { //其余状况返回原参数类型
      return toResolve;
    }
  }
}
private static Type resolveTypeVariable(
    Type context, Class<?> contextRawType, TypeVariable<?> unknown) {
  //获取泛型所在的类(Class)
  Class<?> declaredByRaw = declaringClassOf(unknown);

  //若是获取为null,直接返回该泛型
  if (declaredByRaw == null) {
    return unknown;
  }
  //检测泛型所在类与目标类的关系(同类或者祖类),并取得目标类的该祖类(同类则相等,祖类则祖类与泛型所在类相等)
  Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw);
  //若是该泛型所在类为参数化类型(例如List<String> list的List<String> 为参数化类型ParameterizedType)
  if (declaredBy instanceof ParameterizedType) {
    //获取泛型在泛型所在类的第几个参数
    int index = indexOf(declaredByRaw.getTypeParameters(), unknown);
    //返回该泛型类型
    return ((ParameterizedType) declaredBy).getActualTypeArguments()[index];
  }

  return unknown;
}
private static Class<?> declaringClassOf(TypeVariable<?> typeVariable) {
  //获取泛型所在的类
  GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
  //若是泛型所在的是类的话,返回该类(Class)
  return genericDeclaration instanceof Class ? (Class<?>) genericDeclaration : null;
}
static Type getGenericSupertype(Type context, Class<?> rawType, Class<?> toResolve) {
  //若是泛型所属的类为目标类,返回目标类
  if (toResolve == rawType) {
    return context;
  }
  //若是泛型所属的类并不是目标类,说明是父类的
  //且泛型所属的类为接口
  if (toResolve.isInterface()) {
    //获取目标类(实际上是接口)的全部父接口
    Class<?>[] interfaces = rawType.getInterfaces();
    //遍历全部的父接口
    for (int i = 0, length = interfaces.length; i < length; i++) {
      //若是泛型所属的类为其中之一
      if (interfaces[i] == toResolve) {
        //返回目标类的带泛型的父接口
        return rawType.getGenericInterfaces()[i];
      } else if (toResolve.isAssignableFrom(interfaces[i])) { //若是泛型所属的类为目标类父接口的父接口
        //递归调用,一直查找到泛型所属的类匹配上目标类的某一个上层接口(祖先接口)为止,返回目标类带泛型的祖先接口
        return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);
      }
    }
  }

  //若是目标类不为接口(这个几乎不可能)
  if (!rawType.isInterface()) {
    //当目标类不为对象类时
    while (rawType != Object.class) {
      //获取目标类的父类
      Class<?> rawSupertype = rawType.getSuperclass();
      //若是目标类的父类为泛型所属类
      if (rawSupertype == toResolve) {
        //返回目标类带泛型的父类
        return rawType.getGenericSuperclass();
      } else if (toResolve.isAssignableFrom(rawSupertype)) { //若是泛型所属类为目标类父类的父类
        //递归调用,一直查找到泛型所属的类匹配上目标类的某一个祖类为止,返回目标类带泛型的祖类
        return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);
      }
      //不断向祖类查找,直到找到对象类(Object类)为止
      rawType = rawSupertype;
    }
  }

  //若是实在找不到,返回泛型所属类(Class是Type接口的实现类)
  return toResolve;
}
private static int indexOf(Object[] array, Object toFind) {
  for (int i = 0; i < array.length; i++) {
    if (toFind.equals(array[i])) {
      return i;
    }
  }
  throw new NoSuchElementException();
}
static Class<?> getRawType(Type type) {
  if (type instanceof Class<?>) {
    //若是type为普通类,返回type
    return (Class<?>) type;

  } else if (type instanceof ParameterizedType) { //若是type为参数化类型
    ParameterizedType parameterizedType = (ParameterizedType) type;

    //获取带参数化类型自己的类型
    Type rawType = parameterizedType.getRawType();
    //若是该类型不为类抛出异常
    if (!(rawType instanceof Class)) {
      throw new IllegalArgumentException();
    }
    //返回该类型的类
    return (Class<?>) rawType;

  } else if (type instanceof GenericArrayType) { //若是type为泛型数组类型
    //获取数组的原泛型
    Type componentType = ((GenericArrayType) type).getGenericComponentType();
    //返回数组的类class [Ljava.lang.Object;
    return Array.newInstance(getRawType(componentType), 0).getClass();

  } else if (type instanceof TypeVariable) { //若是type为泛型
    //返回Object类
    return Object.class;

  } else if (type instanceof WildcardType) { //若是type为通配符类型
    //返回通配符上界类型递归后的结果
    return getRawType(((WildcardType) type).getUpperBounds()[0]);

  } else { //都不是则抛出异常
    String className = type == null ? "null" : type.getClass().getName();
    throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
                                       + "GenericArrayType, but <" + type + "> is of type "
                                       + className);
  }
}
@Override
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
  return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);
}
static class FeignInvocationHandler implements InvocationHandler {

  private final Target target;
  private final Map<Method, MethodHandler> dispatch;

  FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {
    this.target = checkNotNull(target, "target");
    this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if ("equals".equals(method.getName())) {
      try {
        Object
            otherHandler =
            args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
        return equals(otherHandler);
      } catch (IllegalArgumentException e) {
        return false;
      }
    } else if ("hashCode".equals(method.getName())) {
      return hashCode();
    } else if ("toString".equals(method.getName())) {
      return toString();
    }
    return dispatch.get(method).invoke(args);
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof FeignInvocationHandler) {
      FeignInvocationHandler other = (FeignInvocationHandler) obj;
      return target.equals(other.target);
    }
    return false;
  }

  @Override
  public int hashCode() {
    return target.hashCode();
  }

  @Override
  public String toString() {
    return target.toString();
  }
}

在Contract中

@Override
public List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType) {
  //检查传入的Class是否有参数,有参数会报错
  checkState(targetType.getTypeParameters().length == 0, "Parameterized types unsupported: %s",
             targetType.getSimpleName());
  //检查传入的Class(通常为接口)是否有多个父接口,有多个父接口会报错,最多支持一个父接口
  checkState(targetType.getInterfaces().length <= 1, "Only single inheritance supported: %s",
             targetType.getSimpleName());
  //若是传入的Class有一个接口
  if (targetType.getInterfaces().length == 1) {
    //检查该接口是否有祖父接口,有会抛出异常,不容许父接口还有父接口
    checkState(targetType.getInterfaces()[0].getInterfaces().length == 0,
               "Only single-level inheritance supported: %s",
               targetType.getSimpleName());
  }
  Map<String, MethodMetadata> result = new LinkedHashMap<String, MethodMetadata>();
  //遍历传入的Class的全部方法
  for (Method method : targetType.getMethods()) {
    //若是传入的Class为Object或者该方法为静态方法或者该方法为接口默认方法
    if (method.getDeclaringClass() == Object.class ||
        (method.getModifiers() & Modifier.STATIC) != 0 ||
        Util.isDefault(method)) {
      //跳到下一个method
      continue;
    }
    //将传入的Class和每个method解析为方法元数据
    MethodMetadata metadata = parseAndValidateMetadata(targetType, method);
    checkState(!result.containsKey(metadata.configKey()), "Overrides unsupported: %s",
               metadata.configKey());
    //将元数据放入map中
    result.put(metadata.configKey(), metadata);
  }
  //返回符合条件的元数据列表
  return new ArrayList<MethodMetadata>(result.values());
}
protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
  //初始化一个方法元数据对象
  MethodMetadata data = new MethodMetadata();
  //设置该对象的返回类型
  data.returnType(Types.resolve(targetType, targetType, method.getGenericReturnType()));
  //设置该对象的configKey
  data.configKey(Feign.configKey(targetType, method));
  //若是目标类(接口)有一个父接口
  if(targetType.getInterfaces().length == 1) {
    processAnnotationOnClass(data, targetType.getInterfaces()[0]);
  }
  processAnnotationOnClass(data, targetType);


  for (Annotation methodAnnotation : method.getAnnotations()) {
    processAnnotationOnMethod(data, methodAnnotation, method);
  }
  checkState(data.template().method() != null,
             "Method %s not annotated with HTTP method type (ex. GET, POST)",
             method.getName());
  Class<?>[] parameterTypes = method.getParameterTypes();
  Type[] genericParameterTypes = method.getGenericParameterTypes();

  Annotation[][] parameterAnnotations = method.getParameterAnnotations();
  int count = parameterAnnotations.length;
  for (int i = 0; i < count; i++) {
    boolean isHttpAnnotation = false;
    if (parameterAnnotations[i] != null) {
      isHttpAnnotation = processAnnotationsOnParameter(data, parameterAnnotations[i], i);
    }
    if (parameterTypes[i] == URI.class) {
      data.urlIndex(i);
    } else if (!isHttpAnnotation) {
      checkState(data.formParams().isEmpty(),
                 "Body parameters cannot be used with form parameters.");
      checkState(data.bodyIndex() == null, "Method has too many Body parameters: %s", method);
      data.bodyIndex(i);
      data.bodyType(Types.resolve(targetType, targetType, genericParameterTypes[i]));
    }
  }

  if (data.headerMapIndex() != null) {
    checkMapString("HeaderMap", parameterTypes[data.headerMapIndex()], genericParameterTypes[data.headerMapIndex()]);
  }

  if (data.queryMapIndex() != null) {
    checkMapString("QueryMap", parameterTypes[data.queryMapIndex()], genericParameterTypes[data.queryMapIndex()]);
  }

  return data;
}

如下这个processAnnotationOnClass为SpringMvcContract中的,而不是Default中的。

@Override
protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {
   //若是父接口没有父接口
   if (clz.getInterfaces().length == 0) {
      RequestMapping classAnnotation = findMergedAnnotation(clz,
            RequestMapping.class);
      if (classAnnotation != null) {
         // Prepend path from class annotation if specified
         if (classAnnotation.value().length > 0) {
            String pathValue = emptyToNull(classAnnotation.value()[0]);
            pathValue = resolve(pathValue);
            if (!pathValue.startsWith("/")) {
               pathValue = "/" + pathValue;
            }
            data.template().insert(0, pathValue);
         }
      }
   }
}
/*
 * AnnotatedElement是全部可注释元素(能够是Class,Method,Field,Constructor,Package等)的接口
 */
@Nullable
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
   //若是该元素不为类,但这里传进来的是目标接口的父接口
   if (!(element instanceof Class)) {
      //获取该元素的注释
      A annotation = element.getAnnotation(annotationType);
      if (annotation != null) {
         return AnnotationUtils.synthesizeAnnotation(annotation, element);
      }
   }

   // Exhaustive retrieval of merged annotation attributes...
   AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationType, false, false);
   return (attributes != null ? AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element) : null);
}

在NamedContextFactory中,NamedContextFactory是FeignContext的父类,而且是一个抽象类

这里咱们能够看到NamedContextFactory实现了ApplicationContextAware接口,便可以获取Spring上下文。

public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
      implements DisposableBean, ApplicationContextAware
//NamedContextFactory的内部接口
public interface Specification {
   String getName();
   //获取配置类数组
   Class<?>[] getConfiguration();
}
//名称与标签配置Spring上下文容器的映射,AnnotationConfigApplicationContext是专门用来作标签配置加载Spring应用上下文。
//从而避免使用xml配置
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
//名称与内部接口实现类的映射
private Map<String, C> configurations = new ConcurrentHashMap<>();
//默认配置类
private Class<?> defaultConfigType;
protected <T> T get(FeignContext context, Class<T> type) {
   //从自己名称的上下文中获取type类的bean实例
   T instance = context.getInstance(this.name, type);
   if (instance == null) {
      throw new IllegalStateException("No bean found of type " + type + " for "
            + this.name);
   }
   return instance;
}
public <T> T getInstance(String name, Class<T> type) {
   //获取该名称的上下文,若是该名称的上下文不存在,则建立一个新的
   AnnotationConfigApplicationContext context = getContext(name);
   //若是type类在该名称上下文中有注册的bean,此处type不能为一个接口
   if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context,
         type).length > 0) {
      //返回该名称上下文中的bean
      return context.getBean(type);
   }
   return null;
}
protected AnnotationConfigApplicationContext getContext(String name) {
   //若是contexts中不包含该名称
   if (!this.contexts.containsKey(name)) {
      synchronized (this.contexts) { //对contexts进行同步锁定
         if (!this.contexts.containsKey(name)) {
            //建立一个新的context,并放入contexts中
            this.contexts.put(name, createContext(name));
         }
      }
   }
   //返回该名称的标签配置上下文
   return this.contexts.get(name);
}
protected AnnotationConfigApplicationContext createContext(String name) {
   //初始化一个标签配置上下文对象
   AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
   //若是内部接口实现类映射中包含该名称
   if (this.configurations.containsKey(name)) {
      //遍历该名称的内部接口实现类的全部配置类(数组)
      for (Class<?> configuration : this.configurations.get(name)
            .getConfiguration()) {
         //将每个配置类注册到标签配置上下文中
         context.register(configuration);
      }
   }
   //遍历内部接口实现类的每一对映射
   for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
      //若是名称以"default."开头
      if (entry.getKey().startsWith("default.")) {
         //遍历该名称的内部接口实现类的全部配置类(数组)
         for (Class<?> configuration : entry.getValue().getConfiguration()) {
            //将每个配置类注册到标签配置上下文中
            context.register(configuration);
         }
      }
   }
   //注册自动装配类和默认配置类
   context.register(PropertyPlaceholderAutoConfiguration.class,
         this.defaultConfigType);
   context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
         this.propertySourceName,
         Collections.<String, Object> singletonMap(this.propertyName, name)));
   if (this.parent != null) {
      // Uses Environment from parent as well as beans
      context.setParent(this.parent);
   }
   context.setDisplayName(generateDisplayName(name));
   //以上注册的bean,context必须刷新才可使用
   context.refresh();
   return context;
}

在BeanFactoryUtils中,首先咱们要先看一张AnnotationConfigApplicationContext继承图,图中代表AnnotationConfigApplicationContext是实现了ListableBeanFactory接口的。

由如下代码能够看出,此处是找出一个Class在Spring上下文中,不管是在哪个层级的上下文(Spring有不少层级的上下文,就上面这张图里标示出来的)注册的,均可以找出来,并把这些类名称放到一个数组中。若是Class是一个接口,则能够找出它全部的被注册到Spring容器的实现类(若是未被Spring上下文注册是找不到的)

public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class<?> type) {
   //这里咱们把ListableBeanFactory lbf就当作标签配置上下文AnnotationConfigApplicationContext对象
   //断言上下文对象不能为null
   Assert.notNull(lbf, "ListableBeanFactory must not be null");
   //获取type的全部类名称(这里包括父类和全部子类)
   String[] result = lbf.getBeanNamesForType(type);
   //此处为真,由于AnnotationConfigApplicationContext也实现了HierarchicalBeanFactory接口
   if (lbf instanceof HierarchicalBeanFactory) {
      //强制转化成HierarchicalBeanFactory(有分层的bean工厂)接口的实例
      HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
      //若是hbf的父bean工厂为ListableBeanFactory(可列表的bean工厂)
      if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
         //递归hbf的父bean工厂,获取父bean工厂中,type的全部类名称(父子类)
         String[] parentResult = beanNamesForTypeIncludingAncestors(
               (ListableBeanFactory) hbf.getParentBeanFactory(), type);
         //组合当前结果和父bean工厂的结果
         result = mergeNamesWithParent(result, parentResult, hbf);
      }
   }
   //返回该结果
   return result;
}
private static String[] mergeNamesWithParent(String[] result, String[] parentResult, HierarchicalBeanFactory hbf) {
   //若是type在父bean工厂没有类名称,直接返回result
   if (parentResult.length == 0) {
      return result;
   }
   //组合当前结果和父bean工厂结果数组
   List<String> merged = new ArrayList<>(result.length + parentResult.length);
   merged.addAll(Arrays.asList(result));
   for (String beanName : parentResult) {
      if (!merged.contains(beanName) && !hbf.containsLocalBean(beanName)) {
         merged.add(beanName);
      }
   }
   //将组合结果由List转回数组返回
   return StringUtils.toStringArray(merged);
}
相关文章
相关标签/搜索