SpringCloud系列之Feign-5.@EnableFeignClients底层机制深度解析

请教下,SpringCloud系列之Feign-5.@EnableFeignClients底层机制深度解析
最新回答
仰天长啸我也要穿越

2024-09-30 01:22:41

@EnableFeignClients 源码比较值得一读,读完之后我们就学会了如何自己写一个注解并成功运用起来了

1.首先我们进入到 @EnableFeignClients注解里面可以看到这个注解里面声明了几个属性,通过名称大概可以看到比如basePackages应该是包路径,value的话应该是个basePackages别名,我们暂且不管,看下这个注解上面有个@Import的注解,点进去这个类来看一下

2.如图可以看到FeignClientsRegistrar这个类实现了三个Spring的类,根据名称大概猜一下,第一个应该是关于类定义注册的类,第二个第三个相信大家可能用过或者了解过就是Spring的Aware的一些类,大致就是加载资源或者环境变量的类

那我们看一下ImportBeanDefinitionRegistrar类里面是什么:

可以看到里面定义了一个方法,那么我们重新返回到FeignClientsRegistrar看下他是怎么实现这个方法的:

这个方法主要干了两件事儿,第一个方法是注册了默认的配置信息,第二个就是注册FeignClients,我们挨个一个个详细的看下:

到了较为详细的源码时候,如果看不懂,我们最好是打断点,当我们启动了Eureka-server,Eureka-client,然后再启动Feign-consumer的时候,断点就可以进来,我们可以看到一些传参的信息:

可以看到这个metedata里面的数据刚好就是在启动类上面的三个注解,并且还带有三个注解的属性信息,下面再给大家看下主类对照下就懂了:

然后我们继续往下面学习:

这一步就比较好理解了,我们拿到EnableFeignClients这个注解的属性信息。

然后就是拼接了一个名称,这个名称就是启动类的前端加了个default.而已,然后registry没变还是传参过来,defaultAttrs.get("defaultConfiguration")这个属性从刚刚断点来看也是空的。调用了一个registerClientConfiguration方法:

这个方法就是使用了Spring的BeanDefinitionBuilder把FeignClientSpecification这个bean给注册到Spring容器中了。

然后我们继续放回到主方法中看下一个方法:

这个方法根据名称registerFeignClients来说应该就是注册FeignClients类了,进入方法中,第一个scanner我们看下:

有点看不懂,没关系,猜一下,可能是扫描类的工具把。

我们继续王下面走,scanner加载了一个resourceLoader这个类,这个类我们可以查一下,他是Spring框架中与资源相关的类,然后再往下看

下面还是获取主类中的注解EnableFeignClients的属性信息

再往下,我们可以从图中看到在属性中获取关于clients的信息,但是没有,然后scanner就加了一个类似过滤器的东东,然后调用了getBasePackages的方法

下面我们看下getBasePackages方法:

看过之前的方法,这个方法就好理解了,首先就还是获取EnableFeignClients的所有属性信息,然后把值都给取出来,取得属性分别是value还是basePackages等关于包路径的属性值,如果都没有获取到,就获取一个默认的包路径

这个包路径断点可以看到就是主类的包路径,所以整体上看,这些逻辑就是首先看注解中有没有关于FeignClient的包路径信息,如果没有配置,那程序就准备从主程序所在的包路径下找所有的FeignClient了。

我们再详细看下:

然后继续看这个registerClientConfiguration方法:

这个方法我们之前看过就是把某个类加载到Spring中所以继续下一步,看registerFeignClient方法:

获取到这个FeignClient的所有属性之后,我们就进行数据处理,把属性信息都赋值给definition

这个方法表示我们把这个类以 按照类型注入 作为属性,然后

这块逻辑就是为了防止两个有同一个父类的FeignClient出现问题所做的,我们应该都遇到过一个问题就是 使用 @Autowire注入类的时候发现报错,说是有两个类不知道注入哪一个,而如果其中一个有@primary注解的话,spring是会优先注入这个类的。

下面就没什么了,直到最后执行了

整个@EnableFeignClients的实现到此执行完毕,这个注解的源码相对来说看起来算是比较清晰明了了,而且对于我们如果有做一个新注解的需求的话,完全可以参照着做,非常具有模板意义。