FeignClient註解屬性configuration不生效問題排查思路
問題背景
我們知道,"如果需要自定義單個Feign配置,Feign的@Configuration 註解的類不能與@ComponentScan 的包重疊,這樣會如果包重疊,將會導致所有的Feign Client都會使用該配置",所以正常使用時,我們在註解上指定單獨自定義的配置,不使其全域性生效。具體使用教程見我的這篇分享。
但有的小夥伴出現了,指定了configuration 卻仍舊不生效的問題,博主本人最近也碰見這個問題,排查成功解決了,分享一下排查思路。
排查思路
- 首先你需要檢查你寫的configuration的包路徑是可以被spring掃描到的
- 如果可以掃描到,請檢查你的@FeignClient中的name屬性是否與其他client重複,如果重複,有機率導致不生效,為什麼是有機率的,參考後續的原始碼挖掘
- 排查你使用的 name 是否與引用jar包中的client重複了,或者乾脆隨便打幾個字母,重新啟動嘗試一下
原始碼挖掘
被@FeignClient註解的介面會在專案啟動時,被spring容器掃描到,開始一系列的準備工作,最重要的是 FeignClientFactoryBean#configureUsingConfiguration()步驟,這個是開始載入你自定義的configuration中的Retryer、RequestInterceptor等等...
FeignClientFactoryBean.java
protected void configureUsingConfiguration(FeignContext context,
Feign.Builder builder) {
Logger.Level level = getOptional(context, Logger.Level.class);
if (level != null) {
builder.logLevel(level);
}
Retryer retryer = getOptional(context, Retryer.class);
if (retryer != null) {
builder.retryer(retryer);
}
ErrorDecoder errorDecoder = getOptional(context, ErrorDecoder.class);
if (errorDecoder != null) {
builder.errorDecoder(errorDecoder);
}
Request.Options options = getOptional(context, Request.Options.class);
if (options != null) {
builder.options(options);
}
Map<String, RequestInterceptor> requestInterceptors = context
.getInstances(this.contextId, RequestInterceptor.class);
if (requestInterceptors != null) {
builder.requestInterceptors(requestInterceptors.values());
}
if (this.decode404) {
builder.decode404();
}
}
從FeignContext類的物件context你可以拿到整個專案所有的FeignClient的上下文引數,debug一下,你可以看到所有的配置:
可以知道存放configuration們的容器其實是一個Map,它們的key是name屬性,這也就解釋了,為什麼有些configuration不生效的原因了。
如果你配置的configuration提前先put進map了,後續的同名configuration的配置就給它覆蓋了。
如果到這你都還沒有解決問題,那麼嘗試從原始碼的堆疊中尋找答案吧。