内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

OpenFeign基本介紹和原理了解-創(chuàng)新互聯(lián)

了解 OpenFeign

OpenFeign 組件的前身是 Netflix Feign 項(xiàng)目。后來 Feign 項(xiàng)目被貢獻(xiàn)給了開源組織,才有了今天使用的 Spring Cloud OpenFeign 組件。
OpenFeign 提供了一種聲明式的遠(yuǎn)程調(diào)用接口,它可以大幅簡化遠(yuǎn)程調(diào)用的編程體驗(yàn)。用一個代碼片段看一下,由 OpenFeign 發(fā)起的遠(yuǎn)程服務(wù)調(diào)用的代碼風(fēng)格是什么樣的。

創(chuàng)新互聯(lián)建站是一家網(wǎng)站設(shè)計(jì)公司,集創(chuàng)意、互聯(lián)網(wǎng)應(yīng)用、軟件技術(shù)為一體的創(chuàng)意網(wǎng)站建設(shè)服務(wù)商,主營產(chǎn)品:成都響應(yīng)式網(wǎng)站建設(shè)公司、品牌網(wǎng)站制作、全網(wǎng)整合營銷推廣。我們專注企業(yè)品牌在網(wǎng)站中的整體樹立,網(wǎng)絡(luò)互動的體驗(yàn),以及在手機(jī)等移動端的優(yōu)質(zhì)呈現(xiàn)。做網(wǎng)站、成都網(wǎng)站建設(shè)、移動互聯(lián)產(chǎn)品、網(wǎng)絡(luò)運(yùn)營、VI設(shè)計(jì)、云產(chǎn)品.運(yùn)維為核心業(yè)務(wù)。為用戶提供一站式解決方案,我們深知市場的競爭激烈,認(rèn)真對待每位客戶,為客戶提供賞析悅目的作品,網(wǎng)站的價值服務(wù)。
String response = helloWorldService.hello("Spring Cloud");

可以發(fā)現(xiàn),使用 OpenFeign 組件來實(shí)現(xiàn)遠(yuǎn)程調(diào)用非常簡單,就像使用本地方法一樣,只要一行代碼就能實(shí)現(xiàn) WebClient 組件好幾行代碼干的事情。而且這段代碼不包含任何業(yè)務(wù)無關(guān)的信息,完美實(shí)現(xiàn)了調(diào)用邏輯和業(yè)務(wù)邏輯之間的職責(zé)分離。

OpenFeign 組件背后的工作流程

OpenFeign 使用了一種動態(tài)代理技術(shù)來封裝遠(yuǎn)程服務(wù)調(diào)用的過程,在上面的例子中看到的 helloWorldService 其實(shí)是一個特殊的接口,它是由 OpenFeign 組件中的 FeignClient 注解所聲明的接口。

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

@FeignClient(value = "hello-world-service")
public interface HelloWorldService {  @PostMapping("/sayHello")   
  String hello(String guestName);
}

遠(yuǎn)程服務(wù)調(diào)用的信息被寫在了 FeignClient 接口中。在上面的代碼里,可以看到,服務(wù)的名稱、接口類型、訪問路徑已經(jīng)通過注解做了聲明。OpenFeign 通過解析這些注解標(biāo)簽生成一個動態(tài)代理類,這個代理類會將接口調(diào)用轉(zhuǎn)化為一個遠(yuǎn)程服務(wù)調(diào)用的 Request,并發(fā)送給目標(biāo)服務(wù)。

OpenFeign 的動態(tài)代理

在項(xiàng)目初始化階段,OpenFeign 會生成一個代理類,對所有通過FeignClient 接口發(fā)起的遠(yuǎn)程調(diào)用進(jìn)行動態(tài)代理。如圖:
在這里插入圖片描述
上圖中的步驟中,在項(xiàng)目啟動階段加載完成的是 1 ~ 3步 ,只有第 4 步(調(diào)用遠(yuǎn)程服務(wù))是發(fā)生在項(xiàng)目的運(yùn)行階段。
關(guān)鍵步驟描述:

  1. 在項(xiàng)目啟動階段,OpenFeign 框架會發(fā)起一個主動的掃包流程,從指定的目錄下掃描并加載所有被 @FeignClient 注解修飾的接口。
  2. OpenFeign 會針對每一個 FeignClient 接口生成一個動態(tài)代理對象,即圖中的 FeignProxyService,這個代理對象在繼承關(guān)系上屬于 FeignClient 注解所修飾的接口的實(shí)例。
  3. 這個動態(tài)代理對象會被添加到 Spring 上下文中,并注入到對應(yīng)的服務(wù)里,也就是圖中的 LocalService 服務(wù)。
  4. LocalService 會發(fā)起底層方法調(diào)用。實(shí)際上這個方法調(diào)用會被 OpenFeign 生成的代理對象接管,由代理對象發(fā)起一個遠(yuǎn)程服務(wù)調(diào)用,并將調(diào)用的結(jié)果返回給 LocalService。
OpenFeign 是如何通過動態(tài)代理技術(shù)創(chuàng)建代理對象的?

OpenFeign 組件加載過程的重要階段,如圖:
在這里插入圖片描述
OpenFeign 動態(tài)代理類的創(chuàng)建過程:

  1. 項(xiàng)目加載:在項(xiàng)目的啟動階段,EnableFeignClients 注解扮演了啟動開關(guān)的角色,它使用 Spring 框架的 Import 注解導(dǎo)入了 FeignClientsRegistrar 類,開始了 OpenFeign 組件的加載過程。
@SpringBootApplication
@EnableFeignClients
public class HelloWorldApplication {public static void main(String[] args) {SpringApplication.run(HelloWorldApplication .class, args);
    }

}
  1. 掃包:FeignClientsRegistrar 負(fù)責(zé) FeignClient 接口的加載,它會在指定的包路徑下掃描所有的 FeignClients 類,并構(gòu)造 FeignClientFactoryBean 對象來解析 FeignClient 接口。
  2. 解析 FeignClient 注解:FeignClientFactoryBean 有兩個重要的功能,一個是解析 FeignClient 接口中的請求路徑和降級函數(shù)的配置信息;另一個是觸發(fā)動態(tài)代理的構(gòu)造過程。
  3. 構(gòu)建動態(tài)代理對象:ReflectiveFeign 包含了 OpenFeign 動態(tài)代理的核心邏輯,它主要負(fù)責(zé)創(chuàng)建出 FeignClient 接口的動態(tài)代理對象。ReflectiveFeign 在這個過程中有兩個重要任務(wù):一個是解析 FeignClient 接口上各個方法級別的注解。將其中的遠(yuǎn)程接口 URL、接口類型(GET、POST 等)、各個請求參數(shù)等封裝成元數(shù)據(jù),并為每一個方法生成一個對應(yīng)的 MethodHandler 類作為方法級別的代理;另一個重要任務(wù)是將這些 MethodHandler 方法代理做進(jìn)一步封裝,通過 Java 標(biāo)準(zhǔn)的動態(tài)代理協(xié)議,構(gòu)建一個實(shí)現(xiàn)了 InvocationHandler 接口的動態(tài)代理對象,并將這個動態(tài)代理對象綁定到 FeignClient 接口上。這樣一來,所有發(fā)生在 FeignClient 接口上的調(diào)用,最終都會由它背后的動態(tài)代理對象來承接。
    MethodHandler 的構(gòu)建過程涉及到了復(fù)雜的元數(shù)據(jù)解析,OpenFeign 組件將 FeignClient 接口上的各種注解封裝成元數(shù)據(jù),并利用這些元數(shù)據(jù)把一個方法調(diào)用“翻譯”成一個遠(yuǎn)程調(diào)用的 Request 請求。
    元數(shù)據(jù)的解析是依賴于 OpenFeign 組件中的 Contract 協(xié)議解析功能。Contract 是 OpenFeign 組件中定義的頂層抽象接口,它有一系列的具體實(shí)現(xiàn),其中 SpringMvcContract 這個類名字中就能看出來,它是專門用來解析 Spring MVC 標(biāo)簽的。
    SpringMvcContract 的繼承結(jié)構(gòu)是 :SpringMvcContract->BaseContract->Contract。
    這里拿一段 SpringMvcContract 的代碼塊,理解它是如何將注解解析為元數(shù)據(jù)的。這段代碼的主要功能是解析 FeignClient 方法級別上定義的 Spring MVC 注解。
// 解析FeignClient接口方法級別上的RequestMapping注解
protected void processAnnotationOnMethod(MethodMetadata data, Annotation methodAnnotation, Method method) {   // 如果方法上沒有使用RequestMapping注解,則不進(jìn)行解析
   // 其實(shí)GetMapping、PostMapping等注解都屬于RequestMapping注解
   if (!RequestMapping.class.isInstance(methodAnnotation)
         && !methodAnnotation.annotationType().isAnnotationPresent(RequestMapping.class)) {  return;
   }

   // 獲取RequestMapping注解實(shí)例
   RequestMapping methodMapping = findMergedAnnotation(method, RequestMapping.class);
   // 解析Http Method定義,即注解中的GET、POST、PUT、DELETE方法類型
   RequestMethod[] methods = methodMapping.method();
   // 如果沒有定義methods屬性則默認(rèn)當(dāng)前方法是個GET方法
   if (methods.length == 0) {  methods = new RequestMethod[] {RequestMethod.GET };
   }
   checkOne(method, methods, "method");
   data.template().method(Request.HttpMethod.valueOf(methods[0].name()));

   // 解析Path屬性,即方法上寫明的請求路徑
   checkAtMostOne(method, methodMapping.value(), "value");
   if (methodMapping.value().length >0) {  String pathValue = emptyToNull(methodMapping.value()[0]);
      if (pathValue != null) { pathValue = resolve(pathValue);
         // 如果path沒有以斜杠開頭,則補(bǔ)上/
         if (!pathValue.startsWith("/") && !data.template().path().endsWith("/")) {pathValue = "/" + pathValue;
         }
         data.template().uri(pathValue, true);
         if (data.template().decodeSlash() != decodeSlash) {data.template().decodeSlash(decodeSlash);
         }
      }
   }

   // 解析RequestMapping中定義的produces屬性
   parseProduces(data, method, methodMapping);

   // 解析RequestMapping中定義的consumer屬性
   parseConsumes(data, method, methodMapping);

   // 解析RequestMapping中定義的headers屬性
   parseHeaders(data, method, methodMapping);
   data.indexToExpander(new LinkedHashMap<>());
}

通過上面的方法可以看到,OpenFeign 對 RequestMappings 注解的各個屬性都做了解析。
如果項(xiàng)目中使用的是 GetMapping、PostMapping 之類的注解,沒有使用 RequestMapping,那么 OpenFeign 也可以解析。以 GetMapping 為例,它對 RequestMapping 注解做了一層封裝。如下代碼片段,這個注解頭上也掛了一個 RequestMapping 注解。因此 OpenFeign 可以正確識別 GetMapping 并完成加載。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {// ...省略部分代碼
}
OpenFeign調(diào)用過程

OpenFeign 其實(shí)底層調(diào)用的是 Feign 的方法,生成了代理類,使用的是 JDK 的動態(tài)代理,然后 bean 注入。
調(diào)用過程,就是代理類作為客戶端向被調(diào)用方發(fā)送請求,接收相應(yīng)的過程。其中,feign 自行封裝了 JDK java.net 相關(guān)的網(wǎng)絡(luò)請求方法,請求過程中還有 Loadbalancer 進(jìn)行負(fù)載均衡;收到響應(yīng)后,還會對響應(yīng)類進(jìn)行解析,取出正確的響應(yīng)信息。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

本文名稱:OpenFeign基本介紹和原理了解-創(chuàng)新互聯(lián)
網(wǎng)頁URL:http://www.rwnh.cn/article40/gdpho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈全網(wǎng)營銷推廣、云服務(wù)器、品牌網(wǎng)站建設(shè)網(wǎng)站導(dǎo)航、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)
灌云县| 电白县| 突泉县| 泰州市| 宝鸡市| 锦州市| 视频| 合作市| 玉田县| 平潭县| 桂平市| 新巴尔虎右旗| 贡觉县| 老河口市| 磴口县| 临西县| 噶尔县| 蒲城县| 岳普湖县| 临夏县| 紫金县| 辉南县| 西城区| 孟连| 崇信县| 崇义县| 铜梁县| 吴忠市| 镶黄旗| 东明县| 贵溪市| 咸阳市| 连州市| 孟州市| 迁安市| 西盟| 黑龙江省| 洪泽县| 临洮县| 南部县| 修水县|