本文是對(duì)《OSGi入門教程》課程的筆記。
OSGi基礎(chǔ)概念
基本概念
OSGi的一些定義
- Open Services Gateway initative 開發(fā)服務(wù)網(wǎng)關(guān)協(xié)議
- 是指Java的動(dòng)態(tài)模塊化系統(tǒng)的一系列規(guī)范啦桌。(OSGi聯(lián)盟,osgi.org)
- OSGi Alliance 組織 以及該組織指制定的一個(gè)基于Java語(yǔ)言的服務(wù)規(guī)范若治。(Wiki)
- Java 平臺(tái)的模塊層菌仁。(《OSGi in Action》)
OSGi生態(tài)
模塊化
將大型系統(tǒng)分解為多個(gè)模塊郊供,通過(guò)設(shè)置模塊的邊界來(lái)改善系統(tǒng)的可維護(hù)性和封裝性疯淫。
Java模塊化的局限性
可見性控制不夠
- 通過(guò)Package來(lái)組織和劃分代碼币绩,可見范圍可以分為Private诉瓦、Package、Protected眠蚂、Public這幾類煞聪。
- 存在的問(wèn)題:如果是Public的話,任何人都可以訪問(wèn)逝慧,希望可以進(jìn)一步控制(一種方案可以是通過(guò)一些模式進(jìn)行模擬實(shí)現(xiàn)昔脯,另一種可以是OSGi)。
Jar包災(zāi)難
- ClassPath中的Jar包在運(yùn)行時(shí)沒(méi)有明確地模塊邊界笛臣。
- 多個(gè)版本的Jar同時(shí)存在時(shí)云稚,加載具有不缺定性。Jar Hell(Jar包災(zāi)難)沈堡。
部署和管理缺少支持
- 模塊的動(dòng)態(tài)更静陈、系統(tǒng)動(dòng)態(tài)演化。
- 插件化開發(fā)诞丽。
OSGi三層架構(gòu)
模塊層:定義了OSGi中的模塊Bundle鲸拥。
- Bundle是一個(gè)具有額外元數(shù)據(jù)的Jar包。
- Bundle定義了包含的包的可見性(對(duì)外暴露哪些模塊)僧免。
- Bundle定義了所依賴的包刑赶。
生命周期層:提供運(yùn)行時(shí)管理和框架訪問(wèn)接口。
- 提供對(duì)模塊生命周期的操作(install,update,start,stop...)懂衩,使得程序外部可以動(dòng)態(tài)管理和演化系統(tǒng)撞叨。
- 定義了運(yùn)行時(shí)上下文的接口,bundle本身可以和OSGi框架進(jìn)行交互浊洞,從而實(shí)現(xiàn)內(nèi)部自我管理牵敷。
服務(wù)層:關(guān)注模塊間的交互。
- 服務(wù)層是JVM中的SOA(面向服務(wù)的架構(gòu))沛申。
- 服務(wù)是動(dòng)態(tài)的劣领,促使你使用基于接口編程。
- OSGi服務(wù)是Java Interface铁材,服務(wù)調(diào)用是Java對(duì)象方法調(diào)用(Lightweight Tech,輕量級(jí)技術(shù))尖淘。
OSGi介紹補(bǔ)充
OSGi嚴(yán)格的模塊化特性的最大優(yōu)勢(shì)
- 基于接口編程,完全隱藏實(shí)現(xiàn)(促進(jìn)你從架構(gòu)上思考)著觉。
- 動(dòng)態(tài)新(對(duì)擴(kuò)展開發(fā)村生,即使是運(yùn)行時(shí))。
OSGi傳播的阻力
- 最初面向的嵌入式領(lǐng)域饼丘,容易被誤解為只是嵌入式技術(shù)趁桃。
- 有些人覺(jué)得OSGi復(fù)雜,人為屬于重量級(jí)。
- Lib支持不夠:很多Lib不能再OSGi環(huán)境下運(yùn)行卫病。
企業(yè)中的OSGi
- 企業(yè)應(yīng)用特點(diǎn):持久化數(shù)據(jù)油啤、數(shù)據(jù)量大、訪問(wèn)并發(fā)等蟀苛。
- 需要模塊化:前端/事務(wù)/持久化分離益咬、運(yùn)行多個(gè)服務(wù)器上、需要協(xié)作化開發(fā)帜平。
- 存在問(wèn)題:企業(yè)開發(fā)中其它框架會(huì)使用TCCL(SPI模式)幽告、反射,這些技術(shù)在OSGi類加載機(jī)制下會(huì)有問(wèn)題裆甩。
小節(jié)
- OSGi提供了更粗粒度的模塊化特征冗锁,可以解決Java模塊化的局限性。
- OSGi中聲明式和基于元數(shù)據(jù)的方法是非侵入式的嗤栓。
- 生命周期層定義了模塊動(dòng)態(tài)且可控的生命周期模型冻河,簡(jiǎn)化了系統(tǒng)管理。
- 服務(wù)層鼓勵(lì)采用基于接口編程的方法抛腕,從而將接口與實(shí)現(xiàn)進(jìn)行分類芋绸。
OSGi模塊層
模塊化
與面向?qū)ο蟮年P(guān)系
- 都是“關(guān)注點(diǎn)分離”(分治)思想的體現(xiàn),但關(guān)注的粒度不一樣担敌。
- 在實(shí)現(xiàn)特定功能時(shí)摔敛,需要設(shè)計(jì)類以及類之間的關(guān)系,此時(shí)需要面向?qū)ο蟮脑瓌t和模式全封。
-
當(dāng)把相關(guān)的類在邏輯上組織在一起的時(shí)候马昙,需要關(guān)注系統(tǒng)模塊和模塊間的關(guān)系。
模塊化的意義
- 解決Java模塊化的局限:可見性控制不夠刹悴、Jar包災(zāi)難行楞、部署和管理缺少支持。
- 通過(guò)顯示定義能力(Export-Package)和依賴(Import-Package),可以優(yōu)化設(shè)計(jì)土匀,讓系統(tǒng)更加“高內(nèi)聚低耦合”(軟件開發(fā)的終極目標(biāo))子房。
- 促進(jìn)協(xié)同開發(fā),提高開發(fā)效率就轧。
Bundle
基本概念
- Bundle是一個(gè)包含代碼证杭、資源、元數(shù)據(jù)妒御,以Jar的形式存在的模塊化單元解愤。
- Jar文件的邊界也是模塊的邊界。Jar包是bundle中代碼的物理容器乎莉。
- Mainifest.mf文件保存了模塊的元數(shù)據(jù)送讲。
元數(shù)據(jù)定義
- 元數(shù)據(jù)信息定義在/META-INF/MANIFEST.MF中奸笤,OSGi R5規(guī)范定義了28個(gè)標(biāo)記。
- 元數(shù)據(jù)有三類標(biāo)記:可讀信息哼鬓、Bundle標(biāo)識(shí)(Identification)监右、代碼可見性。
依賴解析
OSGi類查找順序
- 如果類所在包以“java.”開頭异希,委托給父類加載器秸侣。
- 如果類所在的包在導(dǎo)入包中,委托給導(dǎo)出該包的Bundle宠互。
- 在Bundle自身的類路徑上查找。
多個(gè)提供者的選取規(guī)則
- 已解析的(resolved)的bundle優(yōu)先級(jí)高椭坚,未解析的(installed)bundle優(yōu)先級(jí)低予跌。
-
相同優(yōu)先級(jí)多個(gè)匹配時(shí),版本高者優(yōu)先善茎,版本相同則先安裝的優(yōu)先券册。
uses子句使用
- 使用uses子句來(lái)解決類空間不一致的問(wèn)題。
- uses約束是可傳遞的垂涯。
- 謹(jǐn)慎使用uses,會(huì)大大限制解析的靈活性烁焙。
- 使用場(chǎng)景如下。
- 導(dǎo)出包中的類耕赘,其方法簽名中包含了其Import-Package中的類骄蝇。
- 導(dǎo)出包中的類,繼承了其Import-Packeage中的類操骡。
OSGi生命周期層
基本概念
生命周期管理
- 通過(guò)外部或內(nèi)部對(duì)應(yīng)用進(jìn)行操作九火,完成對(duì)應(yīng)用的“生命周期管理”過(guò)程。
- 對(duì)于非模塊應(yīng)用册招,這些操作是以整個(gè)應(yīng)用為對(duì)象岔激。
- 對(duì)于模塊化應(yīng)用,可以有更細(xì)粒度(針對(duì)某個(gè)模塊)的生命周期管理是掰。
生命周期層的作用
- 在應(yīng)用外部虑鼎,該層精確定義了對(duì)bundle生命周期的相關(guān)操作。
- 在應(yīng)用內(nèi)部键痛,該層定義了bundle訪問(wèn)其執(zhí)行上下文的方式炫彩,為bundle提供了一種與OSGi框架交互的途徑。
- 對(duì)生命周期的操作允許你動(dòng)態(tài)地改變運(yùn)行于框架匯中的bundle組成散休,并以此來(lái)管理和演化應(yīng)用程序媒楼。
生命周期層狀態(tài)轉(zhuǎn)移
使用生命周期層
- BundleActivator是生命周期層的基礎(chǔ)設(shè)施,如下所示。
public interface BundleActivator{
public void start(BundleContext context) throws Exception;
public void stop(BundleContext context) throws Exception;
}
- bundle屬于active時(shí)戚丸,BundleContext才有意義划址,即start方法被調(diào)用和stop方法被調(diào)用的兩個(gè)時(shí)間點(diǎn)之間扔嵌。
- BundleContext包含部署和生命周期管理相關(guān)接口、與bundle間服務(wù)交互相關(guān)的接口夺颤。
-
Bundle定義了一系列API,用于管理已安裝的bundle的生命周期痢缎。
Bundle的更新
兩階段更新
- 兩階段更新:先update,再顯示refresh。
- 為什么兩階段世澜?對(duì)外輸出后独旷,其它模塊會(huì)使用舊版本,需要刷新寥裂,可參考《bundle動(dòng)態(tài)更新》嵌洼。
刷新流程
- 從bundle開始計(jì)算受影響的bundle有向圖。
- 處于ACTIVE狀態(tài)的bundle被停止并被切換至RESOLVED狀態(tài)封恰。
- 處于RESOLVED狀態(tài)的bundle麻养,切換至INSTALLED狀態(tài),這些bundle的依賴關(guān)系不再被解析诺舔。
- 處于UNINSTALLED狀態(tài)的bundle會(huì)從圖中移除鳖昌,同時(shí)也會(huì)被徹底地從框架中移除(GC)。
- 其它bundle如果在框架重啟前處于ACTIVE狀態(tài)低飒,重啟框架會(huì)對(duì)這些bundle及其依賴的bundle進(jìn)行解析许昨。
- 所有工作完成后,框架會(huì)觸發(fā)一個(gè)FrameworkEvent.PACKAGES_REFRESHED事件褥赊。
小節(jié)
- BundleActivator是bundle的入口糕档,與Java應(yīng)用中的main函數(shù)類似。
- BundleContext為應(yīng)用提供執(zhí)行時(shí)操作OSGi框架的方法崭倘。
- Bundle代表了一個(gè)已安裝到框架中的bundle,允許對(duì)其執(zhí)行狀態(tài)進(jìn)行操作翼岁。
OSGi服務(wù)層
基本概念
什么是服務(wù)
- 為別人完成的工作(經(jīng)典定義)。
- 指提供者及其使用者之間的一個(gè)契約司光。服務(wù)可以被替代琅坡,能夠發(fā)布和查找。
- 使用者不關(guān)心具體實(shí)現(xiàn)残家,只關(guān)心約定的契約榆俺。
面向服務(wù)的設(shè)計(jì)
- 降低服務(wù)提供者和使用者之間的耦合,更容易重用組件坞淮。
- 更強(qiáng)調(diào)抽象接口而不是具體實(shí)現(xiàn)茴晋。
- 清晰描述依賴關(guān)系(可以通過(guò)附加元數(shù)據(jù)描述)。
- 支持服務(wù)的多個(gè)實(shí)現(xiàn)方案以及動(dòng)態(tài)替換回窘。
OSGi服務(wù)
OSGi服務(wù)模型
- 擁有一個(gè)集中的服務(wù)注冊(cè)中心诺擅,遵循發(fā)布-查詢-綁定模型。
- 提供者bundle可以將POJOs(Plain Ordinary Java Object)發(fā)布為服務(wù)啡直。
- 使用者bundle可以找到并綁定服務(wù)烁涌。
OSGi服務(wù)注冊(cè)苍碟、更新與注銷
- 服務(wù)注冊(cè)對(duì)象是私有的,不能被別的bundle共享撮执,它們與發(fā)布服務(wù)的bundle的生命周期是綁定的微峰。
- 不推薦使用具體類名進(jìn)行服務(wù)注冊(cè)。
- 當(dāng)一個(gè)bundle停止時(shí)抒钱,任何沒(méi)有被移除的服務(wù)都會(huì)被框架自動(dòng)移除蜓肆。
- 服務(wù)排序:先按service.ranking由大到小排序,然后再按service.id由小到大排序谋币。
- 按屬性查詢:使用LDAP過(guò)濾字符串(LDAP仗扬,Lightweight Directory Access Protocol,輕量目錄訪問(wèn)協(xié)議)蕾额。
服務(wù)使用
// 注冊(cè)中心會(huì)增加一個(gè)使用計(jì)數(shù)厉颤。
A serviceA = (A)bundleContext.getService(reference);
// 完成服務(wù)時(shí)應(yīng)該通知注冊(cè)中心。
bundleContext.ungetService(reference);
服務(wù)監(jiān)聽
服務(wù)可以監(jiān)聽的事件包括:REGISTERED(注冊(cè))凡简、MODIFIED(更改)、UNREGISTERING(注銷)精肃。
OSGi開發(fā)環(huán)境
略秤涩,點(diǎn)擊可查看原文。