引言
??工作日常使用到了feign,幾年前曾看過(guò)源碼,由于當(dāng)時(shí)沒(méi)有閱讀過(guò)spring ioc等部分的源碼,對(duì)于feign這部分理解很多地方都不太清楚。在此五一期間,再閱讀一遍,此系列為記錄閱讀過(guò)程,僅僅提供閱讀思路,如果錯(cuò)誤理解,請(qǐng)及時(shí)指出。
目標(biāo)
- 搞明白Feign實(shí)現(xiàn)原理
- 找到其設(shè)置的擴(kuò)展點(diǎn),用于將來(lái)進(jìn)行擴(kuò)展
RPC (Remote Procedure Call )
??RPC 全稱(chēng)是 Remote Procedure Call ,即遠(yuǎn)程過(guò)程調(diào)用,其對(duì)應(yīng)的是我們的本地調(diào)用。RPC 的目的是:讓我們調(diào)用遠(yuǎn)程方法像調(diào)用本地方法一樣。依稀記得很多年前還學(xué)習(xí)過(guò) Java RMI(Java Remote Method Invocation), 隨著Java Web以及微服務(wù)的興起,已經(jīng)銷(xiāo)聲匿跡,作為遠(yuǎn)程調(diào)用寵兒。Dubbo與Feign是比較常見(jiàn)的RPC技術(shù),話不多說(shuō),今天先簡(jiǎn)單介紹Feign的基本知識(shí),開(kāi)始Feign源碼的閱讀之旅。

什么是Feign
??Feign是Netflix開(kāi)發(fā)的聲明式、模板化的HTTP客戶端,F(xiàn)eign可幫助我們更加便捷、優(yōu)雅地調(diào)用HTTP API。
??Feign可以做到使用 HTTP 請(qǐng)求遠(yuǎn)程服務(wù)時(shí)就像調(diào)用本地方法一樣的體驗(yàn),開(kāi)發(fā)者完全感知不到這是遠(yuǎn)程方法,更感知不到這是個(gè) HTTP 請(qǐng)求。它像 Dubbo 一樣,consumer 直接調(diào)用接口方法調(diào)用 provider,而不需要通過(guò)常規(guī)的 Http Client 構(gòu)造請(qǐng)求再解析返回?cái)?shù)據(jù)。它解決了讓開(kāi)發(fā)者調(diào)用遠(yuǎn)程接口就跟調(diào)用本地方法一樣,無(wú)需關(guān)注與遠(yuǎn)程的交互細(xì)節(jié),更無(wú)需關(guān)注分布式環(huán)境開(kāi)發(fā)。
??Spring Cloud openfeign對(duì)Feign進(jìn)行了增強(qiáng),使其支持Spring MVC注解,另外還整合了Ribbon和Eureka,從而使得Feign的使用更加方便。
SpringCloud中如何使用Feign
??通過(guò)以下4步就可以實(shí)現(xiàn)Feign的調(diào)用實(shí)現(xiàn),實(shí)際在使用過(guò)程中可能會(huì)遇到各種其他的情況,大部分開(kāi)發(fā)人員對(duì)Feign的認(rèn)識(shí)也止步于此,還有一部分開(kāi)發(fā)人員憑借經(jīng)驗(yàn)來(lái)解決問(wèn)題(曾經(jīng)的自己)。
- 引入依賴
<!-- openfeign 遠(yuǎn)程調(diào)用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 啟動(dòng)類(lèi)啟用Feign
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class AuthApplication {
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
- 書(shū)寫(xiě)FeignClient接口
@FeignClient(value = "test-center", fallback = SecurityFeignFallback.class)
public interface TestFeign {
@RequestMapping(value = "/jwt/test", method = RequestMethod.POST)
ResponseResult<String> test(@RequestBody SystemInfo systemInfo);
}
- 注入調(diào)用
@Autowired
private TestFeign testFeign;
public String test() {
SystemInfo systemInfo = new SystemInfo();
testFeign.test(systemInfo);
return "ok";
}
Feign設(shè)計(jì)架構(gòu)
??以下是Feign整體的設(shè)計(jì)架構(gòu),可以看出主要采用的有動(dòng)態(tài)代理技術(shù)以及加解碼

為什么要閱讀源碼
- 求知欲,開(kāi)發(fā)人員基本素養(yǎng)。
- 熟悉非直接研發(fā)代碼,了解整個(gè)調(diào)用鏈路,方便問(wèn)題的排查與開(kāi)發(fā)的擴(kuò)展,豐富解決方案,拓展思路。
- 向開(kāi)源代碼學(xué)習(xí),在日常研發(fā)時(shí),規(guī)范或者優(yōu)雅的進(jìn)行研發(fā),這里并非只有代碼,注釋等同樣值得學(xué)習(xí)。
問(wèn)題
在閱讀源碼之前先提出幾個(gè)很容易遇到的問(wèn)題,可以想一下答案:
- FeignClient已經(jīng)聲明,引入時(shí)為何報(bào)錯(cuò),無(wú)法注入
- 如何加入Request Header
- 如何實(shí)現(xiàn)上傳文件(單個(gè)或者多個(gè)文件)
- 如何將默認(rèn)的Jackson替換為Fastjson
簡(jiǎn)單提出以上4個(gè)問(wèn)題,如果有可以補(bǔ)充的留言區(qū)哦。以上是源碼解析第一章,接下來(lái)將進(jìn)入正題環(huán)節(jié)。
展望
- Feign代碼入口尋找(Feign源碼解析(一))