深入理解SpringCloud源码探究篇 | Feign源码分析

SpringCloud系列:

  1. SpringCloud入门必看例子
  2. 深入理解SpringCloud源码探究篇 | Eureka服务端源码分析
  3. 深入理解SpringCloud源码探究篇 | Eureka客户端源码分析
  4. 深入理解SpringCloud源码探究篇 | ribbon源码分析
  5. 深入理解SpringCloud源码探究篇 | Feign源码分析

按照惯例先来白话文描述下Feign的工作原理

@EnableFeignClients入口,Import了FeignClientsRegistrar进行bean注册,其实际就是筛选出所有@FeignClient注解的接口,为其注册为FeignClientFactoryBean,以及注册配置FeignClientSpecification用于放不同服务名的配置信息类。FeignClientFactoryBean自然是实现类FactoryBean,返回的是getObject代理类,也就是在调用Feign接口时其实际是调用代理对象的ReflectiveFeign.FeignInvocationHandler.invoke,默认调用到SynchronousMethodHandler.invoke,这里面就会调用到Client.execute。LoadBalancerFeignClient实现了Client也就实现execute方法,这里将会进行进行调用ILoadBalancer的chooseServer方法进行以上的服务筛选获取一个服务(也就是利用到了ribbon)。接着就是发起http请求进行具体服务调用了。

 feign的自动配置类FeignRibbonClientAutoConfiguration

具体配置哪些我就不再一一展开了,其中包括LoadBalancerFeignClient,Options,FeignContext,Targeter等bean的注册

 

@EnableFeignClients注解与@FeignClient

使用feign首先是在我们的项目启动类中使用@EnableFeignClients注解进行启动扫描feign接口,同时也在feign接口中采用@FeignClient注解。这里先来看看@EnableFeignClients注解:

从该注解中我们可以看到利用@Import进行引入FeignClientsRegistrar类:

 从以上代码中可以看到FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar类,该类用于bean的注册使用,实现方法registerBeanDefinitions,这里registerBeanDefinitions方法调用了:

registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);

registerDefaultConfiguration方法: 

获取EnableFeignClients注解上的信息默认配置,然后将其信息调用registerClientConfiguration进行注册:

将配置信息放入FeignClientSpecification。

回到上面registerFeignClients方法:

 从以上方法内的代码可以分析出,扫描获取@EnableFeignClients上的信息,以及扫描过滤出包下的所有@FeignClient注解的类。接着进行配置信息的注册以及feign接口的代理类注册:

先是通过getClientName获取FeignClient注解上所写的名字:

然后接着调用registerClientConfiguration方法进行将FeignClient注解上的configuration配置的配置类进行注册交由spring容器,和前面提到的EnableFeignClients默认配置defaultConfiguration一致,注册为FeignClientSpecification,这个会在FeignAutoConfiguration主动配置类中进行注入获取,然后将其配置放入到FeignContext中交由spring容器

接着调用registerFeignClient进行代理类的生成:

从以上我们可以看到将其feign接口注册为FeignClientFactoryBean,而FeignClientFactoryBean实现了FactoryBean:

所以feign接口所拿到的代理实现类是getTarget所返回的对象:

以上可以看出继续调用loadBalance:

 这里在FeignContext拿到LoadBalancerFeignClient,以及Targeter,这些都是自动配置类注册进的bean,然后接着调用到Targeter.target,这里的层次比较多就不一一截图了,最终被返回出来的是这个代理对象(该方法在ReflectiveFeign类下的newInstance):

 到这里feign接口的代理对象就被创建出来了,在使用接口过程实际调用的这是这个代理对象的InvocationHandler.invoke()

 

Feign与Ribbon结合使用

调用Feign时最终执行到的是默认SynchronousMethodHandler.invoke()

这里进到方法后创建RequestTemplate接着调用到executeAndDecode(),该方法会进行以下下操作:

response = client.execute(request, options);

 

LoadBalancerFeignClient实现类Client,这里直接看 LoadBalancerFeignClient的excute方法:

lbClient创建出FeignLoadBalancer,继承关系:

然后执行executeWithLoadBalancer(方法在父类AbstractLoadBalancerAwareClient中):

接着跟进到LoadBalancerCommand的submit:

直接先跟进查看selectServer()方法是如何进行挑选服务的:

 继续跟进:

从以上代码截图中可以看出,最终利用ILoadBalancer来调用其chooseServer方法来挑选出服务,该方法在前面深入理解SpringCloud源码探究篇 | ribbon源码分析该章提及过,最终获取到Server然后进行回调外面传入的operation.call方法(回到前面的AbstractLoadBalancerAwareClient.executeWithLoadBalancer方法):

这就完成了feign与ribbon的结合。

 

 总结

feign接口被初始为一个代理对象,调用时其实际是通过一个代理对象进行调用,最终调用到的是SynchronousMethodHandler.invoke(),利用ILoadBalancer来调用其chooseServer方法来挑选出服务,最后发起切确服务的reuqest请求,这样就完成了feign与ribbon的结合使用

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值