前面我们看过了springcloud熔断器注册中心以及负载均衡,本文我们来看一下springcloud的远程调用客户端Feign的源码
入口org.springframework.cloud.openfeign.EnableFeignClients
![81233d3f5f93e6ba42c5d00a0320666a.png](https://i-blog.csdnimg.cn/blog_migrate/ca2379ed9ff251f3430a14aa5ea7fa88.jpeg)
从注释上我们可以看到这个注解的作用就是扫描feign客户端以及配置信息,并且引入了
org.springframework.cloud.openfeign.FeignClientsRegistrar
接下来我们进入里面看看里面做了啥
![c3516eac8b57d8f20b38c0954456caee.png](https://i-blog.csdnimg.cn/blog_migrate/cbdbd74e306bb997ab170c5d99311381.jpeg)
![c3516eac8b57d8f20b38c0954456caee.png](https://i-blog.csdnimg.cn/blog_migrate/cbdbd74e306bb997ab170c5d99311381.jpeg)
嗯?这不是刚刚我们说的那两个事吗?1、扫描配置类信息;2、扫描客户端
接下来我们看看他是如何扫描配置类信息的
![718edad50dba133f94cd1dd6ad07bdae.png](https://i-blog.csdnimg.cn/blog_migrate/ef610f3be37370f8f39034b7d2c2a55e.jpeg)
可以看到,这里主要就是解析org.springframework.cloud.openfeign.EnableFeignClients注解的属性信息,然后获取默认配置进行注册
进入org.springframework.cloud.openfeign.FeignClientsRegistrar#registerClientConfiguration
![226154692218a9c4eb80f1506384af73.png](https://i-blog.csdnimg.cn/blog_migrate/4c69cccccea917317e812ee49102217a.jpeg)
可以看到这里就是把配置类注入到spring容器里
接下来我们看看第二件事扫描feign客户端
![07c434ffdffd3092cf311d2297b81cd6.png](https://i-blog.csdnimg.cn/blog_migrate/5f64580128ce1a14e1e2b60655ec749d.png)
进入org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients
![b7ccbad115af9fb8514793ba9b1eee37.png](https://i-blog.csdnimg.cn/blog_migrate/e9236aa12f53623c0863c4340b132d18.jpeg)
![67b5456e73a33b8fe1c2d526ee893ec2.png](https://i-blog.csdnimg.cn/blog_migrate/4c5a6cad2432e68c018fbaaf4907c4ec.jpeg)
可以看到这里也就是扫描包含feignClient的类进行注册
接下来进入org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClient中
![53dc436069760cd75e7c5f231e640ecd.png](https://i-blog.csdnimg.cn/blog_migrate/800e031c6cf091edcb9ba3ecc4e81879.jpeg)
可以看到这里主要就是封装一个BeanDefinition然后使用工具进行注册,bean注册这里我们就不用关心了,最终他就是注册到容器里
到这里我们EnableFeignClients注解做的是基本就完事了
接下来我们看一下feign的自动装配都做了啥
![7eb804259f5da665261944ef16098739.png](https://i-blog.csdnimg.cn/blog_migrate/e2fdee743453fb2aafa63647492f3cca.jpeg)
进入org.springframework.cloud.openfeign.FeignAutoConfiguration
![0e78813b72412ab4d958ed838e105916.png](https://i-blog.csdnimg.cn/blog_migrate/1413965b231b456a34367a07eb517b7c.jpeg)
这里注入了一个feign上下文
进入org.springframework.cloud.openfeign.FeignContext这里看看这里都干了啥
![72b101a4d2e27084fad00b266d99f3ac.png](https://i-blog.csdnimg.cn/blog_migrate/6d53354f91b4b8ff4aaeb38d12ea1285.jpeg)
哦,他告诉我们这里创建了一个feign的实例工厂,并且可以从spring上下文获取到feign的实例。
到这里我们初始化阶段就基本完了,接下来我们看看我们是如何从spring容器中获取到一个feign客户端的
回到org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients
我们发现在封装BeanDefinition的时候传入了一个工厂
![89157a0463ffdee415f9eee13bb88e6c.png](https://i-blog.csdnimg.cn/blog_migrate/ec31e6dc043f324c52756c3a3b4c3370.jpeg)
我们都知道工厂bean主要是用来获取bean用,我们去看看他是怎们获取一个bean的
![08b50401614d26943cdf8c47c3e1e3b5.png](https://i-blog.csdnimg.cn/blog_migrate/57e06e60f95f5978d2b6f5315dff7276.jpeg)
进入org.springframework.cloud.openfeign.FeignClientFactoryBean#getObject
![b8e8e991205909fdc4cc83d6cb73f6b9.png](https://i-blog.csdnimg.cn/blog_migrate/442810bd4c30b5cfa9cab2c99087276c.png)
进入org.springframework.cloud.openfeign.FeignClientFactoryBean#getTarget
![e073bb71a6d71420c5b16a8f356d8bfe.png](https://i-blog.csdnimg.cn/blog_migrate/867f3d255bc1b642540764926fb83f08.jpeg)
可以看到这里主要就是获取一个feign上线文,然后利用上下文获取一个构造器,最后调用org.springframework.cloud.openfeign.FeignClientFactoryBean#loadBalance
那么我们想一下这个org.springframework.cloud.openfeign.FeignClientFactoryBean#loadBalance方法里做了啥
![42aa4d75e17dcce65550d94de93e0f34.png](https://i-blog.csdnimg.cn/blog_migrate/57659fc693a64a021d262aa52c2b5abf.jpeg)
这里可以看到,主要是使用feign上下文获取一个客户端然后给构造器设置上最后获取一个目标,调用目标的targer方法
接下来我们看看这个target方法,进入org.springframework.cloud.openfeign.HystrixTargeter#target
![f659e1ce93a3c491b0fc879c7b3fec7d.png](https://i-blog.csdnimg.cn/blog_migrate/241fe60e41df938c8445e2be00d722f0.jpeg)
继续跟进,进入feign.Feign.Builder#target
![c53dc559ac8e88acab830d61da8ba93e.png](https://i-blog.csdnimg.cn/blog_migrate/4e1695ae0069b86adb6b27ef0ade72d4.png)
进入feign.Feign.Builder#build
![d86056e04e6a38465cd0e95fdb771825.png](https://i-blog.csdnimg.cn/blog_migrate/e3ab5d7c42306a9a767725ce6a277c2d.jpeg)
![5774c9eb6d392c7f3ccf83cafe65593d.png](https://i-blog.csdnimg.cn/blog_migrate/f1dc519dfe1e011965e9c09da63fece8.jpeg)
哦这里直接创建了一个feign
![fe66567426424b36ba84952f7ab73683.png](https://i-blog.csdnimg.cn/blog_migrate/a4dacdfdaa93baa0c9b260aad26c256e.jpeg)
再看一下feign.ReflectiveFeign#newInstance
![c6469fbb2e778745efd28f0374a4cd12.png](https://i-blog.csdnimg.cn/blog_migrate/c8c229cf9301c12c521d2efd64dba624.jpeg)
哦,这块就熟悉了吧,他先把目标对象的方法拿出来进行一个封装,然后使用动态dialing创建一个代理对象进行返回
通过前两张图我们可以知道这个handler就是feign.SynchronousMethodHandler
到这里我们就知道了如何获取一个feign客户端,我们接下来看看他是如何进行调用的呢?
从上面获取客户端的过程中我们就知道他是获取到的是一个feign.ReflectiveFeign代理对象
那么我们猜想ReflectiveFeign这里是不是有一个调用的方法呢?
![6bf581abe9041286bf056f643d6e43ff.png](https://i-blog.csdnimg.cn/blog_migrate/d5897963bc2dd738cbe6efdab72635da.jpeg)
![0215036a84c45d8c013efc6cf67d5833.png](https://i-blog.csdnimg.cn/blog_migrate/12b022e3dd0b86c30ff393bc12aa28d0.jpeg)
果然啊,这里确实有一个invoke方法
进入feign.InvocationHandlerFactory
![6d83277289c6a024b0eb75fd0ddc60f5.png](https://i-blog.csdnimg.cn/blog_migrate/db39ecf30ab756fce3ec839a41411635.jpeg)
进入feign.SynchronousMethodHandler#invoke
![3a75c07b7e88720e35f42b073bed667e.png](https://i-blog.csdnimg.cn/blog_migrate/fd5263ef7d667e2c8d030fad7e632cf4.jpeg)
进入feign.SynchronousMethodHandler#executeAndDecode
![d3f8117dd10992459ac073e695de5efa.png](https://i-blog.csdnimg.cn/blog_migrate/ba7ad55506212ec7c532e3295a965777.jpeg)
进入org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#execute
![23c099656e9ecea64a08153f35941ed4.png](https://i-blog.csdnimg.cn/blog_migrate/dbde8b37a8594dff9621ce6fb5dc3cc2.jpeg)
这里主要就是获取客户端基本信息然后进行调用
进入org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#lbClient
![85b0de5b323737ac6fe83a41b0d8578a.png](https://i-blog.csdnimg.cn/blog_migrate/3d72f0de71c5ecd79b06800ff87a6495.png)
进入org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory#create
![6bceb15c977ef7e2f152b701942fdfe8.png](https://i-blog.csdnimg.cn/blog_migrate/4042abd8d32cf645e26559bb9f4038e6.jpeg)
这里主要就是创建客户端并放入缓存
我们回到org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#execute看看是怎么执行的呢
![b4613650b113e06980fb33d1b5fd0904.png](https://i-blog.csdnimg.cn/blog_migrate/55b9d5ae8cc797daee71ab34a627f331.jpeg)
进入com.netflix.client.AbstractLoadBalancerAwareClient#executeWithLoadBalancer
![3c9a75098ceeb27f6feb3d429201e0a6.png](https://i-blog.csdnimg.cn/blog_migrate/c7fa99c1dbb9adbce13de1d0029b184d.jpeg)
好吧,到了这里我就无法继续跟进了,因为后面的都看不懂。。。。这就又回到了RxJava了。
但是我们回到org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient可以发现他实现了Client接口
![a6a854109ad4fd6c9652516e57f9f53b.png](https://i-blog.csdnimg.cn/blog_migrate/ba141bb41030c8af6c02640b61d66129.png)
我们跟进去看看,里面会不会发现什么
![d24f91b4497ff3f4bd73848f99d1cdac.png](https://i-blog.csdnimg.cn/blog_migrate/8b21540c9c8cbe29ff81e4a9152ae3de.jpeg)
看到这里,大家应该可以大胆的猜想,这会不会使用的是http进行发送的请求呢?
跟进去看看
![de33c89eb640d2d62d33d8532639de57.png](https://i-blog.csdnimg.cn/blog_migrate/1a0073613dba2a132e55779521f839cf.jpeg)
![705ade2e6cc8cff6dc928ceca2e195a7.png](https://i-blog.csdnimg.cn/blog_migrate/766f237fbd0f4a73354ffa366131a5d6.jpeg)
哈哈哈,果不其然