OpenFeign原理我个人觉得是非常简单的,如果你对Spring非常了解,知道FactoryBean,以及注入bean的方式,并掌握动态代理,那么自己实现一个类似这样的Http代理客户端是一点问题也没有的!
使用流程
首先我们先过一边常规的使用流程:
1.启动类打上@EnableFeignClients注解
2.然后在调用接口上打上@FeignClient注解,接口方法就是常规Post、Get注解
3.之后在代码中依赖注入这个接口就可以像调用普通方法一样实现Http调用了
思考两个问题,一个接口没有任何实现类能发起调用吗?接口类是怎么被扫描进Bean容器中的?
原理流程
@FeignClient注解
首先我们看是怎么注入容器的,先看看@FeignClient注解,就是一个平平无奇的注解,显然是不会被Spring的扫描机制自动扫描的处理的,那么答案就应该 在@EnableFeignClients注解上了
@EnableFeignClients注解
该注解内有一个@Import注解,显然这就是我们要的,有一个FeignClientsRegistrar类,名称就看得出来是FeignClient的注册类
如果对Spring注入方式不了解的话,看看我之前写的:Bean放入容器的几种方式
FeignClientsRegistrar
他实现了ImportBeanDefinitionRegistrar接口,该接口是往Spring注册BeanDefinition的,所以我们直接去看看他实现的registerBeanDefinitions方法中注册了什么BeanDefinition
BeanDefinition是Bean的定义,在Spring的Bean生成流程中是先有BeanDefinition后有Bean,所以BeanDefinition基本可以认为是一个即将要被注入的Bean
registerBeanDefinitions方法:
扫描后遍历去注册
registerFeignClient方法:
这里就非常的明显了,最后注入了个啥?FeignClientFactoryBean!!,所以最终我们在依赖注入的时候实际上获取的是FactoryBean.getObject所产生的对象!到了这Spring的工作就已经结束了
如果对FactoryBean不了解的,建议先去了解一下
FeignClientFactoryBean
这里的后续流程其实就和Spring没啥关系了,后面就是代理类的生成过程,如果想了解feign是怎么和Ribbon、Hystrix打通的倒是可以继续往下专,这里就不再带着大家往下看了(最后给了个流程图可以自己看,最后发起调用的是RequestTemplate)
不过值得一提的是Feign默认是有一个重试机制的,用的是Retry
,默认是关闭,当然也可以自定义重试机制,这里可能很多人都会忽略,这段代码在(SynchronousMethodHandler)
总流程图
配置项
总结
所以现在懂了吗?
- 通过@EnableFeignCleints触发Spring应用程序对classpath中@FeignClient修饰类的扫猫
- 解析到@FeignClient修饰类后,Feign框架通过扩展Spring Bean Deifinition的注册逻辑,最终注册一个FeignClientFacotoryBean进入Spring容器
- Spring容器在初始化其他用到@FeignClient接口的类时,获得的是FeignClientFacotryBean产生的一个代理对像Proxy.
- 基于java原生的动态代理机制,针对Proxy的调用,都会被统转发给Feign框架所定义的一个InvocationHandler,由该Handler完成后续的HTTP转换,发送,接收,翻译HTTP响应的工作