首先先明白 SpringMvcContract類是做什么的:
該類繼承了Contract.BaseContract並實現了ResourceLoaderAware接口,
其作用就是對RequestMapping、RequestParam、RequestHeader等注解進行解析的。
在了解了SpringMvcContract類的作用后,要想知道該類調用時機,最簡單的辦法就是找一個調用feign接口的方法,打斷點去觀察requestTemplate的生成過程,看在什么時候把注解解析成請求模板的。在項目啟動之前,我就把SpringMvcContract類中的方法打了斷點,但是讓我奇怪的是,在項目啟動的過程中,就直接進到該類的斷點了,難道是在項目啟動時,調用的嗎?帶着這個問題,我放掉了斷點,並讓項目啟動完成,開始調用app-service中的 會員查詢詳情及卡查詢 接口,這個接口調用了ZexMemberFeignClient 的 全渠道會員查詢接口,通過斷點的調試,我發線了requestTemplate的形成流程圖如下:
在encode之后,requestTemplate就已經將請求頭文件、入參等數據封裝好了,並且問題是,在此過程中並未調用SpringMvcContract類去解析注解,反而是在invoke之后,注解就已經被解析了。
然后我百度了feign的實現原理,明白了feign是通過JDK動態代理來生成RequestTemplate的,也就對前面的疑問有了答案:在項目啟動時,會程序包掃描,對包下所有@FeignClient注解的類,並注入到Spring的IOC容器中,而SpringMvcContract類就是在此時提供解析規則,生成MethodHanderMap。在程序調用feign接口時,會通過invoke獲取對應容器下的解析規則,encode之后生成完整的request請求。