日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

dubbo源码解析(一)

發(fā)布時(shí)間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dubbo源码解析(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

大家好,我是烤鴨:

? ? ?今天和大家分享dubbo的源碼解析。


1.SPI

http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html

介紹:
SPI 全稱為 Service Provider Interface,是一種服務(wù)發(fā)現(xiàn)機(jī)制。
SPI 的本質(zhì)是將接口實(shí)現(xiàn)類的全限定名配置在文件中,并由服務(wù)加載器讀取配置文件,加載實(shí)現(xiàn)類。這樣可以在運(yùn)行時(shí),動(dòng)態(tài)為接口替換實(shí)現(xiàn)類。
Dubbo重寫(xiě)了Java原生的SPI。Dubbo SPI 是通過(guò)鍵值對(duì)的方式進(jìn)行配置,按需加載指定的實(shí)現(xiàn)類。
源碼:
com.alibaba.dubbo.common.extension.ExtensionLoader?
getExtension:
獲取拓展類對(duì)象。

createExtension:
1. 通過(guò) getExtensionClasses 獲取所有的拓展類
2. 通過(guò)反射創(chuàng)建拓展對(duì)象
3. 向拓展對(duì)象中注入依賴 (injectExtension)
4. 將拓展對(duì)象包裹在相應(yīng)的 Wrapper 對(duì)象中

將產(chǎn)生的wrapper對(duì)象放到 objectFactory 。
objectFactory 變量的類型為 AdaptiveExtensionFactory,AdaptiveExtensionFactory 內(nèi)部維護(hù)了一個(gè) ExtensionFactory 列表,用于存儲(chǔ)其他類型的 ExtensionFactory。Dubbo 目前提供了兩種 ExtensionFactory,分別是 SpiExtensionFactory 和 SpringExtensionFactory。前者用于創(chuàng)建自適應(yīng)的拓展,后者是用于從 Spring 的 IOC 容器中獲取所需的拓展。?
Dubbo IOC 目前僅支持 setter 方式注入。

2.動(dòng)態(tài)加載

http://dubbo.apache.org/zh-cn/docs/source_code_guide/adaptive-extension.html
介紹:
拓展方法被調(diào)用時(shí),根據(jù)運(yùn)行時(shí)參數(shù)進(jìn)行加載。 Dubbo 會(huì)為拓展接口生成具有代理功能的代碼。然后通過(guò) javassist 或 jdk 編譯這段代碼,得到 Class 類。最后再通過(guò)反射創(chuàng)建代理類,整個(gè)過(guò)程比較復(fù)雜。
源碼:
@Adaptive?
當(dāng) Adaptive 注解在類上時(shí),Dubbo 不會(huì)為該類生成代理類。注解在方法(接口方法)上時(shí),Dubbo 則會(huì)為該方法生成代理邏輯。

com.alibaba.dubbo.common.extension.ExtensionLoader?
getAdaptiveExtension:
創(chuàng)建自適應(yīng)拓展。
createAdaptiveExtension
1. 調(diào)用 getAdaptiveExtensionClass 方法獲取自適應(yīng)拓展 Class 對(duì)象
2. 通過(guò)反射進(jìn)行實(shí)例化
3. 調(diào)用 injectExtension 方法向拓展實(shí)例中注入依賴

getAdaptiveExtensionClass
1. 調(diào)用 getExtensionClasses 獲取所有的拓展類
2. 檢查緩存,若緩存不為空,則返回緩存
3. 若緩存為空,則調(diào)用 createAdaptiveExtensionClass 創(chuàng)建自適應(yīng)拓展類動(dòng)態(tài)生成代碼(類):
代碼生成的順序與 Java 文件內(nèi)容順序一致,首先會(huì)生成 package 語(yǔ)句,然后生成 import 語(yǔ)句,緊接著生成類名等代碼。

// 生成 package 代碼:package + type 所在包 codeBuilder.append("package ").append(type.getPackage().getName()).append(";"); // 生成 import 代碼:import + ExtensionLoader 全限定名 codeBuilder.append("\nimport ").append(ExtensionLoader.class.getName()).append(";"); // 生成類代碼:public class + type簡(jiǎn)單名稱 + $Adaptive + implements + type全限定名 + { codeBuilder.append("\npublic class ").append(type.getSimpleName()).append("$Adaptive").append(" implements ").append(type.getCanonicalName()).append(" {");// ${生成方法}codeBuilder.append("\n}");

動(dòng)態(tài)生成代碼(方法):
Dubbo 不會(huì)為沒(méi)有標(biāo)注 Adaptive 注解的方法生成代理邏輯,對(duì)于該種類型的方法,僅會(huì)生成一句拋出異常的代碼。

for (Method method : methods) {// 省略無(wú)關(guān)邏輯Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);StringBuilder code = new StringBuilder(512);// 如果方法上無(wú) Adaptive 注解,則生成 throw new UnsupportedOperationException(...) 代碼if (adaptiveAnnotation == null) {// 生成的代碼格式如下:// throw new UnsupportedOperationException(// ? ? "method " + 方法簽名 + of interface + 全限定接口名 + is not adaptive method!”)code.append("throw new UnsupportedOperationException(\"method ").append(method.toString()).append(" of interface ").append(type.getName()).append(" is not adaptive method!\");");} else {// 省略無(wú)關(guān)邏輯}// 省略無(wú)關(guān)邏輯 }

?獲取 URL 數(shù)據(jù):
?要為 Protocol 接口的 refer export 方法生成代理邏輯。
?通過(guò)遍歷 refer 的參數(shù)列表即可獲取 URL 數(shù)據(jù),export 參數(shù)列表中沒(méi)有 URL 參數(shù),因此需要從 Invoker 參數(shù)中獲取 URL 數(shù)據(jù)。獲取方式是調(diào)用 Invoker 中可返回 URL 的 getter 方法,如果 Invoker 中無(wú)相關(guān) getter 方法,此時(shí)則會(huì)拋出異常。
?生成后如下:

?refer: if (arg1 == null)?throw new IllegalArgumentException("url == null"); com.alibaba.dubbo.common.URL url = arg1;export: if (arg0 == null)?throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null)?throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null"); com.alibaba.dubbo.common.URL url = arg0.getUrl();

獲取 Adaptive 注解值:
Adaptive 注解值 value 類型為 String[],可填寫(xiě)多個(gè)值,默認(rèn)情況下為空數(shù)組。若 value 為非空數(shù)組,直接獲取數(shù)組內(nèi)容即可。若 value 為空數(shù)組,則需進(jìn)行額外處理。比如 LoadBalance 經(jīng)過(guò)處理后,得到 load.balance

檢測(cè) Invocation 參數(shù):
檢測(cè)方法列表中是否存在 Invocation 類型的參數(shù),若存在,則為其生成判空代碼和其他一些代碼。

生成拓展名獲取邏輯:
本段邏輯用于根據(jù) SPI 和 Adaptive 注解值生成“獲取拓展名邏輯”,同時(shí)生成邏輯也受 Invocation 類型參數(shù)影響,綜合因素導(dǎo)致本段邏輯相對(duì)復(fù)雜。本段邏輯可以會(huì)生成但不限于下面的代碼:

String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol()); //或String extName = url.getMethodParameter(methodName, "loadbalance", "random"); //亦或是String extName = url.getParameter("client", url.getParameter("transporter", "netty"));

生成拓展加載與目標(biāo)方法調(diào)用邏輯:
本段代碼邏輯用于根據(jù)拓展名加載拓展實(shí)例,并調(diào)用拓展實(shí)例的目標(biāo)方法。
以 Protocol 接口舉例說(shuō)明,上面代碼生成的內(nèi)容如下:

com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName); return extension.refer(arg0, arg1);

生成完整的方法:
以 Protocol 的 refer 方法為例,上面代碼生成的內(nèi)容如下:

public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) {// 方法體 }

?

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的dubbo源码解析(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。