问题:

1.@FeignClient怎么解析的。

2.@FeignClient标注的接口放到spring容器里存的是什么。

3.调用@FeignClien接口的方法是怎么执行的

 1.@FeignClient怎么解析的?

首先从@EnableFeignClients入手,这个注解里面引入了FeignClientsRegistrar,这个类实现了ImportBeanDefinitionRegistrar,ImportBeanDefinitionRegistrar这个类主要是注册bean到spring容器的,所以到这里,大概猜测是解析@feignClient接口的类后,把解析的结果注册到spring容器。按照这个猜想继续往下看。

  走到registerBeanDefinitions方法,有两个方法registerDefaultConfiguration,registerFeignClients。registerDefaultConfiguration主要干的事情是:如果@EnableFeignClients注解中的defaultConfiguration不为空,则注入到spring容器中。而registerFeignClients方法则是注入FeignClient的地方。

 进入registerFeignClients,这里会扫描@EnableFeignClients所在类的包及其子包下的标记了@FeignClient类,调用registerFeignClient方法,将被@rFeignClient标注的接口注入到IOC容器中,注入的是FeignClientFactoryBean

 2.@FeignClient注解的接口放到spring容器里存的是什么?

@FeignClient注解的接口放到spring容器是一个FeignClientFactoryBean,但在用@Autowired注入需要实例化的地方,spring在启动时,会调用FactoryBean的getObject方法,getObject方法主要是生成动态代理类:

从Spring上下文中,获取FeignContext这个Bean,这个bean是在哪里注册的呢?是在FeignAutoConfiguration中注册的。 然后判断url属性是否为空,如果不为空,则生成默认的代理类;如果为空,则走负载均衡,生成带有负载均衡的代理类。那么重点关注loadBalance方法。

feignClient创建一个子上下文,然后存入以contextId为key的map中(NamedContextFactory的getContext方法)。此处会返回LoadBalancerFeignClient这个Client。FeignRibbonClientAutoConfiguration会导入相关配置类。 然后会从子上下文中,查找Targeter bean,默认返回的是DefaultTargeter, 最后调用target方法。

所以在@Autowired注入的时候,是注入的标记@FeignClient接口的动态代理类。当在自己的业务类中调用feign接口方法时,会调用FeignInvocationHandler的invoke方法。

3.那注入完成后,OpenFeign远程调用是怎样的呢?

从初始化的流程来看 feign.MethodHandler是feign.SynchronousMethodHandler,而java.lang.reflect.InvocationHandler是feign.ReflectiveFeign.FeignInvocationHandler,然后在调用方法时 首先要进入的就是feign.ReflectiveFeign.FeignInvocationHandler#invoke

下面的代码中有一个 executeAndDecode()方法,该方法通过RequestTemplate生成Request请求对象,然后利用Http Client(默认)获取response,来获取响应信息

 

 client.execute(request, options),默认使用HttpURLConnection发起远程调用,这里的client为LoadBalancerFeignClient。看他的execute方法,最终是通过Ribbon负载均衡器发起远程调用。

posted on 2023-02-19 00:17  路飞_lufei  阅读(38)  评论(0编辑  收藏  举报