背景
上一篇介紹了Feign原始碼初始化的一部分,內容主要是,@EnableFeignClients、@FeignClient這些註解,都支援設定一些自定義的配置類:
A custom @Configuration for all feign clients. Can contain override @Bean definition
for the pieces that make up the client, for instance feign.codec.Decoder,
feign.codec.Encoder, feign.Contract.
每個被@EnableFeignClients、@FeignClient註解的類都會對應生成一個bean,型別為:org.springframework.cloud.openfeign.FeignClientSpecification:
public class FeignClientSpecification implements NamedContextFactory.Specification {
private String name;
private Class<?>[] configuration;
即使沒定義自定義的配置類,這個bean照樣生成,只是裡面的configuration欄位是null。
這些bean都不是spring boot那種自動裝配類,因為自動裝配類一般來說,都是帶條件的,比如要檢測到classpath中有某個類,某個property的值等於xxx。
今天,就簡單介紹下,Feign啟動過程中,自動裝配的那些類。
專案簡介
自動裝配有很多條件都是基於類是否存在來判斷,我們們先看看classpath中有啥,主要就是web、nacos服務發現、feign、loadbalancer。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
當然,這裡是要透過nacos進行服務發現的:
spring.cloud.nacos.discovery.username=111
spring.cloud.nacos.discovery.password=222
spring.cloud.nacos.discovery.server-addr=1.1.1.1:8848
spring.cloud.nacos.discovery.namespace=test
Feign呼叫的client程式碼:
package com.example.demo.demos.nacosdiscoveryconsumer;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient("echo-service-provider")
public interface EchoService {
@GetMapping("/echo/{message}")
String echo(@PathVariable("message") String message);
}
手動梳理裝配類
稍微瞭解spring boot的自動裝配的話,大概知道,在starter那些依賴中,jar檔案一般沒有實質內容,沒有class啥的,主要的內容還是pom檔案,裡面定義了該starter依賴的那些jar:
pom依賴主要包含feign自身、spring對feign的整合、spring-loadbalancer:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>11.10</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<version>3.1.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.1.6</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
我們看看spring-cloud-openfeign-core這個依賴,這個spring-cloud-openfeign-core-3.1.7.pom呢,裡面定義了很多底層依賴,而spring-cloud-openfeign-core-3.1.7.jar,則不再是無實質內容了:
大家看到我上圖框的spring.factories檔案,大概就知道,這個東西是和自動裝配有關係的。
我們開啟看看:
裡面主要就是定義了,需要自動裝配的配置類。
比如第一個類:org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration
這些類得特徵是:都是有條件的,這也符合自動裝配的邏輯,自動裝配就是猜測你需要某些類,猜測那是需要依據的,依據就是:檢查你的各種上下文,就跟現在那些短影片推薦一樣的,猜你喜歡嘛。
這邊簡單彙總下,就是這5個自動裝配類:
org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration,\
org.springframework.cloud.openfeign.FeignAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignContentGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration
接下來,看看spring-loadbalancer那個依賴,盤一盤它:
spring-cloud-starter-loadbalancer-3.1.6.jar,和其他starter一樣,裡面啥都沒有;
spring-cloud-starter-loadbalancer-3.1.6.pom,主要依賴如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>3.1.6</version>
<scope>compile</scope>
</dependency>
該依賴如下:
主要包含如下幾個自動裝配類:
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration,\
org.springframework.cloud.loadbalancer.security.OAuth2LoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerStatsAutoConfiguration
至於nacos,也是一樣的套路盤起來,但是,它要直接一點,直接starter裡面就是實質內容了:
引入的自動配置類有:
com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\
com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration,\
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration,\
com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration
但以上就完了嗎,不是。spring-cloud-loadbalancer是屬於spring-cloud-commons的,在commons的jar包中,也有相關的自動配置類:
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
這邊彙總下吧:
org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration,\
org.springframework.cloud.openfeign.FeignAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignContentGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration,\
org.springframework.cloud.loadbalancer.security.OAuth2LoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerStatsAutoConfiguration
com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\
com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration,\
com.alibaba.cloud.nacos.NacosServiceAutoConfiguration,\
com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerDefaultMappingsProviderAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
這一下,就是幾十個自動裝配類,真他麼多。
注意,這裡面還有兩個名字相同,包名不同的:
自動配置類最終引入了哪些bean
自動裝配類都是相當複雜的,基於各種條件的計算,很多都不是一眼就能看出來的,有些和順序還息息相關,比如,ConditionalOnMissingBean,這個就很有意思,在沒有bean存在的情況下才自動裝配,但我之前遇到過,有兩個自動裝配類,都加了這個註解,那,最終到底是哪個自動裝配進去呢?
所以,如果專案複雜,可以考慮開啟如下日誌開關:
logging.level.org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener=DEBUG
就會列印如下的日誌,哪些裝配了,哪些沒裝配,一目瞭然:
spring boot actuator的actuator/conditions也支援動態檢視這個資訊,甚至可以看到各個spring容器的:
如果想知道某個自動裝配類中,哪些bean匹配了,哪些bean沒匹配上,只能ctrl + f了,比如Feign這個裝配類:
org.springframework.cloud.openfeign.FeignAutoConfiguration
相當於匹配上了如下兩個bean:
這邊累計彙總下,裝配成功的:
-
org.springframework.cloud.openfeign.FeignAutoConfiguration及內部的:
FeignAutoConfiguration、
FeignAutoConfiguration.DefaultFeignTargeterConfiguration
FeignAutoConfiguration.DefaultFeignTargeterConfiguration#feignTargeter -
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration,內部類/method:無,這個類是靠import引入其他configuration的
-
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration
LoadBalancerAutoConfiguration#zoneConfig
-
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration#loadBalancerRequestFactory
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration#loadBalancerRequestFactory
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig#restTemplateCustomizer
-
BlockingLoadBalancerClientAutoConfiguration
BlockingLoadBalancerClientAutoConfiguration#blockingLoadBalancerClient
BlockingLoadBalancerClientAutoConfiguration#loadBalancerServiceInstanceCookieTransformer
BlockingLoadBalancerClientAutoConfiguration#xForwarderHeadersTransformer
-
LoadBalancerCacheAutoConfiguration
內部略,太多了,寫了也記不住
-
NacosDiscoveryAutoConfiguration
NacosDiscoveryAutoConfiguration#nacosProperties
NacosDiscoveryAutoConfiguration#nacosServiceDiscovery
-
NacosServiceRegistryAutoConfiguration
NacosServiceRegistryAutoConfiguration#nacosAutoServiceRegistration
NacosServiceRegistryAutoConfiguration#nacosRegistration
-
NacosDiscoveryClientConfiguration
-
NacosServiceAutoConfiguration
-
UtilIPv6AutoConfiguration
-
AsyncLoadBalancerAutoConfiguration
-
LoadBalancerDefaultMappingsProviderAutoConfiguration
以上都是匹配上的,沒匹配的都沒寫。這邊寫了一抹多,供查閱吧,重點的有一個要先摘出來說,它是屬於沒匹配上的:
LoadBalancerNacosAutoConfiguration:
Did not match:
- @ConditionalOnProperty (spring.cloud.loadbalancer.nacos.enabled=true) did not find property 'spring.cloud.loadbalancer.nacos.enabled' (OnPropertyCondition)
這是一個nacos包裡的關於loadbalancer的自動配置類,當初就是因為這個類,讓我遇到了些問題,才好好研究了下feign,寫了這幾篇,可以說的上是為了這盤醋包了這頓餃子,後面的文章會再說說這個類。