1. 程式人生 > >Dubbo——擴充套件點載入機制

Dubbo——擴充套件點載入機制

一、getAdaptiveExtension()方法:獲取擴充套件點實現類的介面卡類例項。從ExtensionLoader.cachedAdaptiveInstance變數中獲取,若為空,則呼叫createAdaptiveExtension方法建立介面卡類的例項,並將介面卡類的例項快取到cachedAdaptiveInstance變數中。

createAdaptiveExtension方法:完成介面卡類的例項化並對介面卡類的例項物件中是擴充套件點介面的成員變數初始化值。

1)呼叫getAdaptiveExtensionClass方法,建立介面卡類的class物件;

2)呼叫Class.newInstance方法完成class物件的例項化;

3)呼叫injectExtension方法完成例項化物件中成員變數的初始化工作。

getAdaptiveExtensionClass方法:建立擴充套件點實現類的介面卡類。

1)呼叫getExtensionClasses方法,獲取擴充套件點的所有實現類;

2)擴充套件點的實現類中已經有使用了@Adaptive註解的類,則該類即作為介面卡類,即ExtensionLoader.cachedAdaptiveClass 變數值;

3)若沒有實現類使用@Adaptive註解,則動態生成一個介面卡類,具體的實現呼叫createAdaptiveExtensionClass方法中完成。

getExtensionClasses方法

:獲取擴充套件點實現類的Map物件。

1)檢查快取ExtensionLoader.cachedClasses 變數中是否有值,若有則直接返回;

2)若沒有快取,則呼叫loadExtensionClasses方法獲取Map物件,並存入ExtensionLoader.cachedClasses變數中。

loadExtensionClasses方法:載入擴充套件點的實現類。

1)獲取ExtensionLoader.type引數值的類的SPI註解,獲取該註解的value值,若該值不為空且只有一個值的話,則儲存ExtensionLoader.cachedDefaultName 物件,作為預設實現類使用;若為空則表示沒有指定預設的實現類;但SPI註解的value值一定不能設定多個。

2)呼叫loadFile方法解析以ExtensionLoader.type的類名來命名的檔案內容,並返回Map物件,該物件的每個K-V即為檔案中的一行內容,key=類簡稱,value=class物件;

loadFile方法:逐行讀取以ExtensionLoader.type引數值的類名來命名的檔案內容;ExtensionLoader.type的值是在ExtensionLoader.getExtensionLoader方法呼叫時傳入的。以ExtensionFactory為例,檔案內容的格式如下。

對每行的解析工作如下:

1)等號右邊為實現類的類名。等號左邊為該類的簡稱;若只寫類名,則以一定的規則來獲取類的簡稱,具體見下面的步驟實現;左邊的簡稱也可以是以逗號分隔的多個簡稱;

2)對等號右邊的類使用Class.forName方法建立class物件,後續對該class物件進行操作;

3)該class物件必須實現了ExtensionLoader.type引數指定的介面;

4)該class物件是否使用了@Adaptive註解,若使用了則將該class物件儲存到ExtensionLoader.cachedAdaptiveClass 變數中,在每個檔案中的所有實現類最多隻能有一個類使用了@Adaptive註解;該行解析結束,繼續下一行;若沒有使用@Adaptive註解的類,則進行下面的解析步驟;

5)該class物件是否有ExtensionLoader.type引數的建構函式,若有則表示可以進行封裝,將該class存入ExtensionLoader.cachedWrapperClasses 變數中,該行解析結束,繼續下一行的解析;例如Protocol介面的擴充套件點檔案中的ProtocolFilterWrapper類的記錄,該實現類有一個Protocol引數的建構函式,故是在建立Protocol的擴充套件點實現類的例項時用該類封裝一層,若沒有,則繼續下面的解析步驟;

6)若等號左邊為空或者該行沒有等號,則堅持該class物件是否使用了@Extension註解,若使用了則取該註解的value值作為該class物件的簡稱;若沒有使用@Extension註解,但實現類的類名是以介面名結尾的,則取類名的前部分為簡稱;但若不是以介面名結尾的類名,則以類名為該類的簡稱;

7)檢查class物件是否使用了@Activate註解;若使用則獲取該註解,並存入ExtensionLoader.cachedActivates物件中,key為類的簡稱,若有多個簡稱則取第一個;

8)遍歷所有的類簡稱,將class物件和每個類簡稱存入ExtensionLoader.cachedNames物件中,其中key=class物件,value=類簡稱;將每個類簡稱和class物件存入Map物件並返回,key=類簡稱,value=class物件;

createAdaptiveExtensionClass方法:該方法在執行時動態建立介面卡類。

1)動態生成介面卡類的程式碼,下面列出了部分介面的動態介面卡類的程式碼:CacheFactory、Cluster、ConfiguratorFactory、Dispatcher、HttpBinder、MonitorFactory、Protocol、ProxyFactory、RegistryFactory、RouterFactory、ThreadPool、Transporter、Validation、ZookeeperTransporter,具體程式碼見《附件一》。在生成介面卡類時,若介面中沒有宣告帶@Adaptive註解的方法,則不生成介面卡類,若有,則在生成介面卡類時,對帶註解的方法重寫;

2)編譯介面卡類程式碼,建立Class物件。編譯器也是通過ExtensionLoader類來動態擴充套件的,預設選擇JavassistCompiler編譯器。

injectExtension方法:對於非ExtensionFactory.Class物件,利用ExtensionFactory的擴充套件實現類的物件獲取成員變數的初始化值,實現程式碼如下:

1)獲取公有的set方法,解析出成員變數的名稱。

2)呼叫ExtensionFactory.getExtension方法獲取成員變數的值。

3)通過反射的方式呼叫set方法完成成員變數值的注入。


ExtensionFactory.getExtension方法:在ExtensionFactory的檔案中,包含了AdaptiveExtensionFactory類,該類使用了@Adaptive註解,所以ExtensionFactory介面的介面卡為AdaptiveExtensionFactory類,故呼叫的是該介面卡類的getExtension方法。

1)在該方法中遍歷ExtensionFactory擴充套件檔案中的所有ExtensionFactory物件的getExtension方法,程式碼如下:


2)目前有SpiExtensionFactory和SpringExtensionFactory兩種;第一,對於SpiExtensionFactory.getExtension方法,根據成員變數的型別從擴充套件點中載入該物件,程式碼如下:


第二,對於SpringExtensionFactory.getExtension 方法,從Spring的上下文中獲取該成員變數的Bean物件,程式碼如下:


二、getExtension(String name)方法:返回指定名字的擴充套件類例項,

1)如果指定名字的擴充套件類不存在,則拋異常。

2)如果指定的名字為“true”,則返回預設的實現類例項,即name= cachedDefaultName;

3)從ExtensionLoader.cachedInstances:ConcurrentHashMap變數中獲取該name的例項;

4)若Map中沒有該name的例項,則呼叫createExtension方法建立該例項,並儲存到快取中。

createExtension(String name)方法:建立擴充套件點實現類的例項物件。

1)呼叫getExtensionClasses方法,獲取type引數的檔案內容;並從Map物件中獲取name的Class物件,若沒有則拋異常;

2)從全域性變數ExtensionLoader.EXTENSION_INSTANCES:ConcurrentMap<Class<?>, Object> 中獲取該class的例項,若沒有,則建立該Class物件的例項,並快取到上面的Map變數中;

3)呼叫injectExtension方法完成成員變數的初始化值注入工作;

4)遍歷cachedWrapperClasses變數,利用以type介面為引數的建構函式建立每個封裝類,故對擴充套件類的例項進行了封裝。並呼叫injectExtension方法對封裝類的成員變數進行初始化工作;

5)返回的例項是經過封裝之後的例項物件。

三、getActivateExtension(URL url, String key, String group)方法:主要是獲取當前擴充套件的所有可自動啟用的實現類的例項列表exts:List<T>。

1)呼叫getExtensionClasses方法,載入當前擴充套件介面的所有實現,會獲取到當前Extension中所有@Active實現,賦值給cachedActivates變數;

2)遍歷cachedActivates集合,檢查集合中每個類中@Active註解的group值是否與入參的值一致,若一致,則加入exts列表中;

3)使用ActivateComparator對exts列表的集合進行排序,排序的依據主要是@Active註解的before、after、order的值來定;

4)檢查中是否有key引數值,若有則將這些引數值的類加入到exts列表中;例如在服務暴露時,key=“service.filter”,則從URL中獲取該引數的值,該值是在<dubbo:service>標籤的filter屬性中配置的服務提供方遠端呼叫過程攔截器名稱,多個名稱用逗號分隔;

5)最後將所有的exts列表返回

相關推薦

Dubbo——擴充套件載入機制

一、getAdaptiveExtension()方法:獲取擴充套件點實現類的介面卡類例項。從ExtensionLoader.cachedAdaptiveInstance變數中獲取,若為空,則呼叫createAdaptiveExtension方法建立介面卡類的例項,並將介面卡類的例項快取到cachedAda

Dubbo擴充套件載入機制

概述 來源:  Dubbo的擴充套件點載入從JDK標準的SPI(Service Provider Interface)擴充套件點發現機制加強而來。 Dubbo改進了JDK標準的SPI的以下問題: JDK標準的SPI會一次性例項化擴充套件點所有實現,如果有擴充套件實現

Dubbo 擴充套件載入機制:從 Java SPI 到 Dubbo SPI

SPI 全稱為 Service Provider Interface,是一種服務發現機制。當程式執行呼叫介面時,會根據配置檔案或預設規則資訊載入對應的實現類。所以在程式中並沒有直接指定使用介面的哪個實現,而是在外部進行裝配。 要想了解 Dubbo 的設計與實現,其中 Dubbo SPI 載入機制是必須瞭解

擴充套件載入機制(ExtensionLoader)

概述 來源: Dubbo的擴充套件點載入從JDK標準的SPI(Service Provider Interface)擴充套件點發現機制加強而來。 Dubbo改進了JDK標準的SPI的以下問題: JDK標準的SPI會一次性例項化擴充套件點所有實現,如果有

dubbo擴充套件機制

spring是如何啟動容器的 常見的一種在本地使用main方法啟動spring的方法 public static void main(String[] args) throws Exception { ClassPathXmlAp

Dubbo擴充套件機制分析

一、擴充套件點配置詳見我在《Java的SPI機制分析》文章中關於Dubbo的SPI機制的介紹,在此不再贅述。二、擴充套件點流程分析之SPI    下面以Container載入的過程為例,來說明SPI擴充套件的實現流程:所有加上@SPI註解的擴充套件點可以有不同的擴充套件,Co

Dubbo 的 SPI 機制(三)(Extension 擴充套件補充)

相關部落格: Dubbo的SPI機制(一)(Java的SPI) Dubbo的SPI機制(二)(Dubbo優化後的SPI實現)   Dubbo 的 Extension 主要是基於 SPI 思想實現的自己的 SPI 的工具。  在上一篇部落格(Dubbo的SP

Dubbo/Dubbox的服務暴露(二)-擴充套件機制

上文書留的疑問,這兩句到底在幹啥 Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, regis

Dubbo原始碼分析——擴充套件機制

Dubbo作為開源框架,必須要提供很多的可擴充套件點。Dubbo的擴充套件點載入採用了微核心外掛式的開發模式,它是比較符合OCP原則。 微核心 由一個外掛生命週期管理容器,構成微核心, 核心不包括任何功能,這樣可以確保所有功能都能被替換,並且框架實現的功能,

Dubbo剖析-增強SPI中擴充套件自動包裝的實現

一、前言 在Spring AOP中可以使用多個切面對指定類的方法進行增強,在Dubbo中也提供了類似的功能,在dubbo中你可以指定多個Wrapper類對指定的擴充套件點的實現類的方法進行增強 二、一個例子 Protocol protocol = ExtensionLoader.getEx

Dubbo原始碼實現四:Dubbo中的擴充套件與SPI

       SPI的全稱是ServiceProviderInterface,即服務提供商介面。直白的說,它主要用來實現一個可擴充套件的Java應用。有人會覺得這就是建立在面向介面程式設計下的一種為了使元件可擴充套件或動態變更實現的規範,常見的類SPI的設計有JDBC、JN

Dubbo擴充套件機制:ExtensionLoader

一、前言     Dubbo的ExtensionLoader是實現“微核心+外掛式”的重要元件,它基於java spi機制卻又提供瞭如下擴充套件:jdk spi僅僅通過介面類名獲取所有實現,而ExtensionLoader則通過介面類名和key值獲取一個實現Adaptive實

DexClassLoader和PathClassLoader類載入機制

分析 sbin 分享 return bject _id ise 否則 nts 0x00 在DexClassLoader和PathClassLoader載入Dex流程一文中,我們分析了dex文件怎樣形成了DexFile結構體。本文中解說類載入機制,實際上就是生

聊聊Dubbo - Dubbo可擴展機制實戰

Java摘要: 在Dubbo的官網上,Dubbo描述自己是一個高性能的RPC框架。今天我想聊聊Dubbo的另一個很棒的特性, 就是它的可擴展性。1. Dubbo的擴展機制在Dubbo的官網上,Dubbo描述自己是一個高性能的RPC框架。今天我想聊聊Dubbo的另一個很棒的特性, 就是它的可擴展性。 如同羅馬不

《深入理解Java虛擬機器》個人讀書總結——虛擬機器類載入機制

我們都知道Java虛擬機器是用來執行我們編譯好的.class檔案的,class檔案中夾帶類的各種資訊,虛擬機器要執行這些檔案,第一件事就是要載入到虛擬機器中,這就引出了這次總結的問題——虛擬機器是如何載入這些class檔案的?載入後虛擬機器是怎麼處理檔案中夾帶的資訊的? 類載入機制

tomcat執行載入機制,dns地址解析,tcp/ip三握四揮(全)

一.瞭解從輸入url到顯示頁面過程中都發生了什麼:    1.通過url並利用DNS解析出目的主機的ip地址;     2.找到目標主機,建立TCP/IP連線;    3.Tomcat監聽

JVM的虛擬機器類載入機制

首先,我們要知道為什麼會存在類的載入機制。Java語言編寫的.java在經過編譯器編譯後會生成.class檔案,這個和C\C++語言是不一樣的。 C語言它們是會被編譯生成為本地機器碼,然後在被執行。這種做法的缺點就是無法完成編寫程式碼的跨平臺使用。想想就知道,windows下編譯好的程式碼在li

關於Class物件、類載入機制、虛擬機器執行時記憶體佈局的全面解析和推測

簡介: 本文是對Java的類載入機制,Class物件,反射原理等相關概念的理解、驗證和Java虛擬機器中記憶體佈局的一些推測。本文重點講述瞭如何理解Class物件以及Class物件的作用。 歡迎探討,如有錯誤敬請指正 如需轉載,請註明出處 http://www.cnblogs.com/nul

JVM原理(二)類載入機制與GC演算法

一. 類的載入機制 過程 將.class的二進位制資料讀入記憶體,放入方法區中 在堆中建立一個java.lang.Class物件,封裝類在方法區中的資料結構,並提供訪問方法區資料結構的介面 類的生命週期 類的載入過程

php自動載入機制

為什麼要實現自動載入機制? 在大專案中,就不用每次include/require檔案,省心又高效,只要你不嫌累的話,就可以不使用。 一、spl_autoload_register 語法: sql_autoload_register(callback $function_n