微内核架构模式
寫本篇主要是用來后面寫一篇可擴展性軟件設(shè)計打好基礎(chǔ)。?
微內(nèi)核定義: ?
???? 微內(nèi)核是內(nèi)核的一種精簡形式。將通常與內(nèi)核集成在一起的系統(tǒng)服務(wù)層被分離出來,變成可以根據(jù)需求加入選件? 這樣就可提供更好的可擴展性和更加有效的應(yīng)用環(huán)境。使用微內(nèi)核設(shè)計,對系統(tǒng)進行升級,只要用新模塊替換舊模塊,不需要改變整個操作系統(tǒng)。?
微內(nèi)核架構(gòu)模式來源于操作系統(tǒng),本文主要講解微內(nèi)核模式在應(yīng)用軟件中的如何實現(xiàn)。?
微內(nèi)核架構(gòu)模式組成: ?
一般由下面幾個部分組成:微內(nèi)核、內(nèi)核、擴展服務(wù)(我更喜歡叫做擴展插件)。?
內(nèi)核由幾個最基本服務(wù)組成,微內(nèi)核完成加載內(nèi)核里所有的基本服務(wù)。?
內(nèi)核基本服務(wù)在應(yīng)用軟件中通常是指那些與業(yè)務(wù)無關(guān)的服務(wù),如資源加載服務(wù)等。?
整個系統(tǒng)就是由微內(nèi)核、內(nèi)核(即幾個基本服務(wù),廣義來講我稱它為插件,所以是容器自帶的幾個默認插件,能提供基本服務(wù))、擴展服務(wù)(廣義來講我稱它為插件,只不過是業(yè)務(wù)系統(tǒng)寫的插件讓微內(nèi)核擴展進來的)。?
抽象來講就是由微內(nèi)核和許多插件組成。如下圖?
?
微內(nèi)核做了什么事??
微內(nèi)核主要負責(zé)插件的生命周期管理,插件的加載,替換,卸載。?
對于加載,替換,卸載都有兩種方式,靜態(tài)與動態(tài)。動態(tài)的更加復(fù)雜。?
插件是什么??
插件一般由以下幾部分組成:插件暴露的接口(我一般稱為叫API),插件內(nèi)部實現(xiàn),插件擴展點以及插件配置。插件擴展點我一般設(shè)計為SPI,因為它符合(java中的API/SPI的概念,關(guān)于API/SPI請參考 API/SPI可擴展設(shè)計原則 )。
整個插件組成示意圖如下?
?
以讀數(shù)據(jù)插件為例,讀數(shù)據(jù)插件主要提供讀數(shù)據(jù)服務(wù),插件暴露接口叫做DataReadAPI。假設(shè)是網(wǎng)站前臺系統(tǒng)。插件的內(nèi)部實現(xiàn)是先讀緩存,后讀數(shù)據(jù)庫。把讀緩存與讀數(shù)據(jù)庫抽象出來一個接口叫DataReadSPI。在內(nèi)部實現(xiàn)只要讀取插件擴展點getExtensions(DataReadSPI.java)得到一個DataReadSPI列表,順序執(zhí)行即可(順序執(zhí)行必須是前面執(zhí)行的結(jié)果為空時再往下執(zhí)行)。?
如果實現(xiàn)了擴展點有兩個:如圖中的DataReadCacheImpl和DataReadDBImpl,那這兩個擴展點在插件配置時把緩存配在前面。于是就形成先讀緩存,如果緩存讀不到就讀數(shù)據(jù)。?
看一下代碼比較容易明白 ?
Java代碼?? 微內(nèi)核框架端?? public?interface?Plugin?{?? ?????? ????void?init(PluginContext?pluginContext);?? ?????? ????<T>?List<T>?getExtension(Class<T>?extensionClassName);?? }?? ?? public?class?PluginManager?{?? ?? ????public?static?<T?extends?Plugin>?T?getPlugin()?? ????{?? ????????//返回插件?? ????????return?null;?? ????}?? ???? }?? ?? public?interface?DataReadAPI?extends?Plugin?{?? ?? ????Object?read(String?key);?? }?? ?? public?interface?DataReadSPI?{?? ????Object?read(String?key);?? }?? ?? public?class?DefaultDataReadImpl?extends?AbstractPlugin?implements?DataReadAPI?{?? ?? ????@Override?? ????public?Object?read(String?key)?{?? ????????List<DataReadSPI>?extensions?=?getExtension(DataReadSPI.class);?? ????????for?(DataReadSPI?extension?:?extensions)?{?? ????????????Object?result?=?extension.read(key);?? ????????????if?(result?!=?null)?{?? ????????????????return?result;?? ????????????}?? ????????}?? ????????return?null;?? ????}?? }??
Java代碼?? 客戶端或叫應(yīng)用端代碼及配置,即微內(nèi)核框架的使用端?? public?class?DataReadCacheImpl?implements?DataReadSPI?{?? ?? ????@Override?? ????public?Object?read(String?key)?{?? ????????return?null;?? ????}?? }?? ?? public?class?DataReadDBImpl?implements?DataReadSPI?{?? ?? ????@Override?? ????public?Object?read(String?key)?{?? ????????return?null;?? ????}?? }?? ?? 插件擴展的配置文件?? <plugins>?? ????<plugin?id="dataReadAPIPluginID">?? ????????<extensions>?? ????????????<extension?interfaceClassName="com.liyh.devine.web.spi.DataReadSPI">?? ????????????????<implements>?? ????????????????????<implment?beanName="DataReadCacheImpl"?/>?? ????????????????????<implment?beanName="DataReadDBImpl"?/>?? ????????????????</implements>?? ????????????</extension>?? ????????</extensions>?? ????</plugin>?? </plugins>?? ?? 業(yè)務(wù)代碼?? public?class?Client?{?? ????public?static?void?main(String[]?args)?? ????{?? ????????DataReadAPI?dataReadAPI?=?PluginManager.getPlugin("dataReadAPI");?? ????????Object?result?=?dataReadAPI.read("key");?? ????????System.out.println(result);?? ????}?? }??
解釋一下: ?
客戶端使用框架提供的插件服務(wù),即插件暴露的API--->DataReadAPI,框架滿足不了客戶端的功能可以實現(xiàn)自己的擴展,如DataReadCacheImpl,DataReadDBImpl。插件一般會提供默認的實現(xiàn),只不過本例默認實現(xiàn)為空,只是簡單調(diào)用一下擴展點的功能就返回了。?
這里比較巧, API與SPI是一樣的,其實一般SPI是API實現(xiàn)過程中開放的擴展點,一般可以比較小。比如RenderAPI,用于渲染的API,它的SPI可能就是一個PullToolFacotry,PullToolFacotry主要返回PullTool。當(dāng)應(yīng)用使用微內(nèi)核框架的Render插件時,可以擴展自己的PullTool返回給框架。?
總結(jié) ?
微內(nèi)核模式的核以是插件管理與及協(xié)調(diào)插件之間的調(diào)用。插件是可以整個被替換,插件本身是一個很大粒度的擴展點。同時插件可以提供自己的小粒度擴展點。這樣整個系統(tǒng)就是由一個微內(nèi)核加很多插件組成一個具備很強的擴展性的系統(tǒng)。
微內(nèi)核定義: ?
???? 微內(nèi)核是內(nèi)核的一種精簡形式。將通常與內(nèi)核集成在一起的系統(tǒng)服務(wù)層被分離出來,變成可以根據(jù)需求加入選件? 這樣就可提供更好的可擴展性和更加有效的應(yīng)用環(huán)境。使用微內(nèi)核設(shè)計,對系統(tǒng)進行升級,只要用新模塊替換舊模塊,不需要改變整個操作系統(tǒng)。?
微內(nèi)核架構(gòu)模式來源于操作系統(tǒng),本文主要講解微內(nèi)核模式在應(yīng)用軟件中的如何實現(xiàn)。?
微內(nèi)核架構(gòu)模式組成: ?
一般由下面幾個部分組成:微內(nèi)核、內(nèi)核、擴展服務(wù)(我更喜歡叫做擴展插件)。?
內(nèi)核由幾個最基本服務(wù)組成,微內(nèi)核完成加載內(nèi)核里所有的基本服務(wù)。?
內(nèi)核基本服務(wù)在應(yīng)用軟件中通常是指那些與業(yè)務(wù)無關(guān)的服務(wù),如資源加載服務(wù)等。?
整個系統(tǒng)就是由微內(nèi)核、內(nèi)核(即幾個基本服務(wù),廣義來講我稱它為插件,所以是容器自帶的幾個默認插件,能提供基本服務(wù))、擴展服務(wù)(廣義來講我稱它為插件,只不過是業(yè)務(wù)系統(tǒng)寫的插件讓微內(nèi)核擴展進來的)。?
抽象來講就是由微內(nèi)核和許多插件組成。如下圖?
?
微內(nèi)核做了什么事??
微內(nèi)核主要負責(zé)插件的生命周期管理,插件的加載,替換,卸載。?
對于加載,替換,卸載都有兩種方式,靜態(tài)與動態(tài)。動態(tài)的更加復(fù)雜。?
插件是什么??
插件一般由以下幾部分組成:插件暴露的接口(我一般稱為叫API),插件內(nèi)部實現(xiàn),插件擴展點以及插件配置。插件擴展點我一般設(shè)計為SPI,因為它符合(java中的API/SPI的概念,關(guān)于API/SPI請參考 API/SPI可擴展設(shè)計原則 )。
整個插件組成示意圖如下?
?
以讀數(shù)據(jù)插件為例,讀數(shù)據(jù)插件主要提供讀數(shù)據(jù)服務(wù),插件暴露接口叫做DataReadAPI。假設(shè)是網(wǎng)站前臺系統(tǒng)。插件的內(nèi)部實現(xiàn)是先讀緩存,后讀數(shù)據(jù)庫。把讀緩存與讀數(shù)據(jù)庫抽象出來一個接口叫DataReadSPI。在內(nèi)部實現(xiàn)只要讀取插件擴展點getExtensions(DataReadSPI.java)得到一個DataReadSPI列表,順序執(zhí)行即可(順序執(zhí)行必須是前面執(zhí)行的結(jié)果為空時再往下執(zhí)行)。?
如果實現(xiàn)了擴展點有兩個:如圖中的DataReadCacheImpl和DataReadDBImpl,那這兩個擴展點在插件配置時把緩存配在前面。于是就形成先讀緩存,如果緩存讀不到就讀數(shù)據(jù)。?
看一下代碼比較容易明白 ?
Java代碼??
Java代碼??
解釋一下: ?
客戶端使用框架提供的插件服務(wù),即插件暴露的API--->DataReadAPI,框架滿足不了客戶端的功能可以實現(xiàn)自己的擴展,如DataReadCacheImpl,DataReadDBImpl。插件一般會提供默認的實現(xiàn),只不過本例默認實現(xiàn)為空,只是簡單調(diào)用一下擴展點的功能就返回了。?
這里比較巧, API與SPI是一樣的,其實一般SPI是API實現(xiàn)過程中開放的擴展點,一般可以比較小。比如RenderAPI,用于渲染的API,它的SPI可能就是一個PullToolFacotry,PullToolFacotry主要返回PullTool。當(dāng)應(yīng)用使用微內(nèi)核框架的Render插件時,可以擴展自己的PullTool返回給框架。?
總結(jié) ?
微內(nèi)核模式的核以是插件管理與及協(xié)調(diào)插件之間的調(diào)用。插件是可以整個被替換,插件本身是一個很大粒度的擴展點。同時插件可以提供自己的小粒度擴展點。這樣整個系統(tǒng)就是由一個微內(nèi)核加很多插件組成一個具備很強的擴展性的系統(tǒng)。
總結(jié)
- 上一篇: 《软件架构设计》读书笔记
- 下一篇: 面向服务架构