Feign的作用是根据接口生成代理类,代理类的作用是发起请求并处理结果。

@EnableFeignClients注解其实是@Import(FeignClientsRegistrar.class),根据SpringBoot注册bean的逻辑,由于FeignClientsRegistrar是一个ImportBeanDefinitionRegistrar,会调用其registerBeanDefinitions方法,里面有两个方法,registerDefaultConfiguration和registerFeignClients,前者是向工厂注册@EnableFeignClients注解中defaultConfiguration属性对应的值,这些配置类的类型是FeignClientSpecification,beanName以default开头。后者是扫描并注册@FeignClient注解的类,首先根据@EnableFeignClients注解的属性去确定要扫描的包,@EnableFeignClients的五个属性,除了刚才说的defaultConfiguration,还有value、basePackages、basePackageClasses以及clients四个,这四个中前三个和第四个是互斥的,如果clients中有属性,取所有的client类所在的包的并集,其他三个属性就不管了;如果clients属性的值为空集合,那么把value、basePackages指向的包和basePackageClasses中的类所在的包取并集;如果四个属性都为空,那么默认是@EnableFeignClients注解的那个类(比如启动类)所在的包。之后扫描所有包中的@FeignClient注解的类,先把注解中configuration属性的值注册了,这些配置类的类型也是FeignClientSpecification,beanName是服务名clientName。

和ribbon一样,feign的配置的优先级也是四层,spring工厂---默认configuration---defaultConfiguration---clientName对应的configuration,后者覆盖前者。

每个FeignClient注解的接口,beanDefinition中,beanClass是FeignClientFactoryBean,接口的类名放到type属性中,primary属性为true所以优先级在fallback之前。

注入的时候,返回的是一个动态代理类,逻辑是FeignClientFactoryBean.getObject---getTarget---loadBalance---targeter.target---feign.target---ReflectiveFeign.newInstance---熟悉的InvocationHandler,反射调用每个方法的时候,用的是targetToHandlersByName.apply方法产生的SynchronousMethodHandler的invoke方法,核心是LoadBalancerFeignClient的execute,这就到了ribbon的范畴。

因为hystrix的设计针对的是服务数量非常庞大的情况,以后再写。

fallback只有在hystrix使用的时候才有效。