@EnableFeignClients和@FeignClient两个注解就实现了Feign的功能
@EnableFeignClients注解把带有@FeignClient注解的类或接口用FeignClientFactoryBean类注册到Spring中
它引入了FeignClientsRegistrar客户端注册类
FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口,那么在registerBeanDefinitions()中就会解析和注册BeanDefinition,主要注册的对象类型有两种:
注册缺省配置的配置信息
注册那些添加了@FeignClient的类或接口
registerFeignClients方法扫描类路径,对所有的FeignClient生成对应的 BeanDefinitio 。同时又调用了registerClientConfiguration 注册配置的方法,这里是第二处调用。这里主要是将扫描的目录下,每个项目的配置类加载的容器当中。调用 registerFeignClient 注册对象
registerFeignClient注册FeignClient对象向Spring中注册了一个bean,bean的名称就是类或接口的名称,bean的实现类是FeignClientFactoryBean,其属性设置就是我们在@FeignClient中定义的属性。那么下面我们在Controller中对FeignService的的引入,实际就是引入了FeignClientFactoryBean 类
FeignClientFactoryBean类实现了FactoryBean类,那么当从ApplicationContext中获取该bean的时候,实际调用的是其getObject()方法。返回调用getTarget()方法
FeignClientFactoryBean实现了FactoryBean的getObject、getObjectType、isSingleton方法;实现了InitializingBean的afterPropertiesSet方法;实现了ApplicationContextAware的setApplicationContext方法
getObject调用的是getTarget方法,它从applicationContext取出FeignContext,然后构造Feign.Builder并设置了logger、encoder、decoder、contract,之后通过configureFeign根据FeignClientProperties来进一步配置Feign.Builder的retryer、errorDecoder、 request.Options、requestInterceptors、queryMapEncoder、decode404
初步配置完Feign.Builder之后再判断是否需要loadBalance,如果需要则通过loadBalance方法来设置,不需要则在Client是LoadBalancerFeignClient的时候进行unwrap
FeignClientFactoryBean.getObject()具体返回的是一个代理类,具体为FeignInvocationHandler,
FeignInvocationHandler实现了InvocationHandler,是动态代理的代理类。
当执行非Object方法时进入到this.dispatch.get(method)).invoke(args)
dispatch是一个map集合,根据方法名称获取MethodHandler。具体实现类为SynchronousMethodHandler
SynchronousMethodHandler
SynchronousMethodHandler内部创建了一个RequestTemplate对象,是Feign中的请求模板对象。内部封装了一次请求的所有元数据。
retryer中定义了用户的重试策略。
调用executeAndDecode方法通过client完成请求处理,client的实现类是LoadBalancerFeignClient