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的配置就給它覆蓋了。
如果到這你都還沒有解決問題,那么嘗試從源碼的堆棧中尋找答案吧。