關於osgi.net ,想必大家也聽說過,以下是自己在學習osgi.net 過程中整理出來的內容,供大家學習參與使用。
1. OSGI.NET 與UIOSP
OSGi是Open Service Gateway Initiative的縮寫,Wiki對其的定義為:一方面它指OSGi Alliance組織,它是由IBM、Oracle、BEA、SAP等國際IT巨頭組成的OSGi聯盟組;另一方面指該組織制定的一個基於Java語言的服務規范——OSGi服務平台(Service Platform)。OSGi服務平台是一個動態的模塊化框架:支持模塊化與插件化、具有熱插拔與動態特性、支持SOA、支持模塊擴展、提供安全性支持等。
OSGi.NET插件框架提供了模塊化與插件化、面向服務架構和模塊擴展三大功能,適用於控制台、WinForm、Windows服務、WPF、ASP.NET和移動平台等任意.NET應用環境。
OSGi.NET是OSGi規范移植到.NET平台的服務規范。UIOSP是XAUI Open Service Platform縮寫,即尤埃開放服務平台,它是OSGi.NET規范的實現,由西安尤埃信息技術有限公司提供。UIOSP完整實現了OSGi規范的移植,提供了模塊化與插件化、面向服務架構支持、模塊可擴展支持三大功能。UIOSP完善支持控制台應用程序、Windows服務應用程序、Windows窗體應用程序、WPF應用程序和ASP.NET應用程序等各種運行環境,並且支持Windows Mobile。
本文將讓您體驗使用Visual Studio.NET 2008 SP1 + SQLServer 2005 Express如何一步一步的基於UIOSP構建一個ASP.NET插件應用程序。目前UIOSP支持VS2005 SP1+/VS2008+/VS2010+開發環境,支持.NET Framework 2.0
1.1OSGI.NET 插件的程序結構:
基於OSGi.NET插件框架的應用程序體系結構如下圖所示。在這里,應用程序由主程序和插件組成。主程序是具體的應用環境的入口,它用於啟動OSGi.NET插件框架並進入插件框架暴露出來的入口點;應用插件則是實現軟件不同功能的業務模塊。

1.2 OSGi.NET插件框架優點:
- 開放、規范、統一:符合規范的模塊均可被OSGi.NET插件框架加載。
- 快速集成:將模塊放在插件模塊即實現功能集成。
- 高度可重用:僅通過拷貝即可實現重用,無需修改任何代碼。
- 熱插拔與動態:每一個模塊都可被動態安裝、啟動、停止和卸載。
- 標准模塊化與模塊物理隔離:模塊具有統一規范且互相獨立。
- 面向服務編程支持:提供基於面向服務架構編程模型以支持模塊通訊。
- 動態可擴展:通過暴露擴展點實現動態擴展。
- 多環境支持:支持各種.NET應用環境。
2. OSGI.NET 模塊化和插件化
2.1 模塊化和插件化的特點:
- 物理隔離:基於UIOSP開發的模塊是一個物理隔離的可單獨部署的模塊,每一個模塊擁有獨立的文件夾、類型空間、資源和類加載器。模塊間互相獨立互相隔離且互不影響。
- 高度可重用:模塊的重用不需要再更改任何代碼,只需要將模塊拷貝到UIOSP指定的插件目錄下,它的功能便向其它模塊暴露。
- 規范化:模塊具有統一的標准,每一個模塊的目錄結構、模塊配置都是統一的,開發方法也完全一致。
- 快速集成:僅需要將模塊都拷貝到指定的插件目錄就能夠實現模塊功能的快速集成,無需再更改任何的代碼。
- 易部署和升級:通過拷貝即可實現部署和升級。
核心思想是封裝,即邏輯和物理兼顧的封裝。邏輯封裝,即OOP干的事兒,封裝變化,面向接口編程。要真的應用在具體業務邏輯上時,是得需要花些功夫和實踐的,對於OSGi的最佳實踐來說,尤其重要。

物理 封裝,即“物理隔離”,隔離的層次級別很低,到了具體的實體文件。首先,不像是普通的.NET程序,如WinForm,默認情況下,功能程序集文件都必須是在bin目錄下,和主程序一塊兒,如Web,文件都是在同一個目錄層次中,核心邏輯也是在這個啟動路徑的bin目錄中,他們是緊密聯系的,無法分開存放的。OSGi的目錄結構是可以自定義的,當然這些路徑都是在一個已經定義好的范圍之內,在這個范圍內任意位置的程序集都可以被訪問的到。比如你可以把主程序放在C盤,功能模塊文件放在D盤。原理上講,就是OSGi.NET改變了.NET默認的加載順序和機制,允許程序動態加載指定路徑的程序集。
其次,就是物理級別的“封裝變化”,對於一個程序來說,每個子功能模塊,根據需求的不同,對整體而言是可變的,也是不停變化的,以前只是將邏輯封裝在一個程序集里,那么是否可以將多個關聯程序集再封裝在一個“模塊”里呢?以前是內部的封裝,現在是內部和外部一起封裝,更抽象的封裝。邏輯封裝的表現形式是一個程序集,通常就是一個具體名字的dll,這里物理的封裝就是一個具體名字的文件夾,在這個文件夾里包含了他所需的多個基本的程序集。理論上說,最佳場景應該是邏輯上、物理上與其他封裝好的模塊之間相互獨立且隔離的,這樣的話,我們能很簡單的從文件結構上提煉出模塊之間的關系以及整個軟件功能的組成,這為以后的更新、維護、部署甚至重用都帶來了好處。比如一個WinForm上的封裝好的數據訪問模塊可以直接復制到一個Web上無需改動,即可使用,這也就是所謂的“高度可重用”,“快速集成”以及“易部署和升級”,他們依賴的就是比較好的邏輯和物理封裝,還有可設置的加載路徑
3.面向服務架構支持
面向服務的體系結構:SOA,也是OSGi.NET中一個重要功能,主要是為了各個模塊可以以一種統一和通用的方式進行交互。以下是官方文檔描述:
- 服務綁定模型:支持典型的“服務注冊 – 服務搜索 – 服務綁定”的服務綁定模型。服務提供商想服務注冊表注冊服務,服務消費者搜索服務注冊表並綁定需要的服務。
- 接口與實現隔離:每一個服務由“接口 + 實現”組成,接口相當於服務契約,而實現則是實現服務接口的具體類的實例。
這里的“服務綁定模型”,像是一個服務總線,用來存儲和檢索各種服務。而SOA就是將應用程序的不同功能單元通過定義良好的接口和契約聯系起來,稱為服務,它具有中立的接口定義,沒有強制綁定到特定的實現上,松耦合。
硬件中的系統總線:

在OSGI.NET,它與硬件系統總線相似,差不多是同樣一個目的,但更側重於接口和具體實現的物理隔離,即所謂的“按需所用”,結合后面將提到的“即插即用”,將會使整個軟件具有更好的靈活性和配置性,以適應未來各種不同的“改變”,無論外部或者內部。
4. OSGi.NET“服務總線”的實現
OSGi.NET的“服務總線”功能是以服務的形式發布的,有兩種注冊服務方式:
- 一個是在激活器當中,通過IBundleContext.AddService來添加一個指定接口和此接口實現的一個實例。
- 一個是在Manifest.xml當中,通過編輯器添加來完成。
服務注冊完成后,可通過GetService來獲取一個指定接口類型的此接口實現的所有實例或者通過GetFirstOrDefaultService來獲取一個指定接口類型的此接口實現的第一個或默認實例。這兩個方法可以通過激活器里的IBundleContext還有運行時環境BundleRuntime得到。
OSGI.NET 的服務總線可以用 IoC 容器來實現,基效果可能 會更好,OSGI.NET目前只提供一個較輕量級的解決方案,並沒有引入 IoC 容器。
以下是服務總線關鍵部分的實現代碼:


5. 模塊可擴展支持
OSGI.NET 支持更高級的模塊擴展策略,具體含義如下(官方文檔):
- 擴展點:通過標准XML節點<ExtensionPoint>來定義一個模塊向其它模塊暴露的擴展點。暴露擴展點的模塊會監聽並處理其它模塊對其的擴展。
- 擴展:通過標准XML節點<Extension>來定義一個模塊對暴露擴展點的模塊的擴展。這個XML節點會通過擴展點變更事件傳遞到暴露擴展點的模塊。
- 動態擴展:模塊在啟動和停止時,會分別向平台注冊和卸載相應的擴展點及擴展,該平台通過模塊上下文暴露擴展點變更事件來處理動態的擴展信息。
- 零耦合:模塊的擴展沒有任何的耦合,僅通過標准XML來配置。

OSGi.NET的擴展點和擴展都是定義在相應模塊的Mainfest.xml文件中的,非常容易維護和更改。模塊與模塊之間就可以完成“擴展點和擴展”,當然主程序中啟動的運行時環境也能直接處理指定“擴展點”的“擴展”。
擴展點的定義,用 <ExtensinPoint> 節點來配置;
<?xml version="1.0" encoding="utf-8"?> <Bundle xmlns="urn:uiosp-bundle-manifest-2.0" SymbolicName="WorkspaceShell" InitializedState="Active"> <Activator Type="WorkspaceShell.Activator" Policy="Immediate" /> <Runtime> <Assembly Path="WorkspaceShell.dll" Share="false" /> </Runtime> <ExtensionPoint Point="ToolBar"/> <ExtensionPoint Point="MainMenu"/> <ExtensionPoint Point="Navigation"/> </Bundle>
對擴展點進行擴展,用 <Extension>節點來進行配置:

6. 熱插拔與動態支持
OSGI.NET 支持熱插拔與動態支持,具體內容如下()官方文檔):
- 熱插拔:所有的模塊都可以被動態的添加和卸載。
- 生命周期:模塊生命周期狀態由“已安裝、已解析、正在啟動、已激活、正在停止、已停止、已卸載”組成,每一個生命周期狀態下,模塊提供的功能都可能不同。
- 動態:當模塊執行任何生命周期操作時,模塊會動態的想外界暴露或者隱藏它提供的功能,比如動態提供服務、擴展或者其它功能。
- 遠程部署:支持模塊遠程部署,比如遠程安裝、啟動、停止和卸載模塊,或者訂閱模塊倉庫中模塊變更並同步。
7. 關於遠程部署
OSGI.NET 部署的相關內容:
- 它是在線的,而不是離線,也就是不需要將程序關閉,用戶可在正常情況使用下,部署模塊
- 由於ASP.NET的特殊性,需要將“運行時”重啟,但Web本身就是非持久性連接,處理恰當的話,對最終用戶影響不是很大。WinForm不受影響
OSGi.NET對模塊的處理並不是安裝和卸載這么簡單,它的生命周期如下:

這里“停止(Stopping)”和“卸載(Uninstalled)”需要稍加說明一下,停止是模塊將自己的生命進程交還給運行時環境前最后的一個狀態,而卸載是運行時環境將模塊結束前的最后一個狀態。簡單的說,
安裝、解析、卸載只能由運行時環境來管理,而啟動、激活、停止是模塊本身可一同參與的;停止的模塊依然在運行時環境管理中,只不過模塊不能再管理自己的狀態,但其他模塊可通過運行時環境對它進行控制;卸載的模塊,在下次重啟並刪除之前,依然在運行時環境管理中;安裝和啟動,類似卸載和啟動;解析和具體的模塊加載過程,可參照前文“模塊化和插件化”實例部分。
插件運行的完整過程(動態性)

8. 插件啟動配置(Manifest.xml)

- “當框架激活時立即啟動Bundle”,這個選項如果勾選上的話,則這個模塊(Bundle)會按照安裝、解析、啟動、激活順序執行。如果不勾選,則到安裝后就停止了,如果這個模塊還被其他模塊依賴,則會忽略這個配置,直接運行到激活。還需要注意,每次更改這個選項時,須將此模塊中的persistent.xml刪除掉,否則無法看到效果。persistent.xml用來記錄最后一次的初始化狀態。
1.1 當然你可以通過編碼的方式將它啟動起來,例如

2. “晚激活,即當Bundle的類被加載是再激活”。這個有點兒類似.NET的晚激活策略,當存在“激活器”時,也就說如果勾選,則模塊會從安裝到解析便停止執行,而當別的模塊需要引用它的某個類時會自動繼續執行啟動和激活,理論上可以減少不必要的消耗
9. 遠程部署
- 整個要部署的插件文件夾壓縮成zip包后刪除這個文件夾。壓縮包放到一個稍后可以訪問到的位置,如D:\

2. 運行起整個主程序,默認的APE選項將不會出現。接着我們打開“遠程管理工具”,輸入字母l,這時也沒有OSGi.NET.APEDecoderPlugin。保留着主程序不要關閉它。
3. 在遠程管理工具里輸入i "OSGi.NET.APEDecoderPlugin" "D:\OSGi.NET.APEDecoderPlugin.zip" "D:\cnblogs.com\OSGi.NET\Demo4\OSGi.NET.AudioPlayerShell\OSGi.NET.AudioPlayerShell\bin\plugins\FormatTypes\Lossless\OSGi.NET.APEDecoderPlugin",並回車,可以看到提示已經安裝成功

4. 激活,OSGi.NET.APEDecoderPlugin處於安裝(installed),而非激活(Active),還需要啟動它,繼續輸入s 6
10.模塊擴展支持
動態信息注入,優點:
- 被注入方不需要知道將會被誰注入,保證了邏輯的單一性,易於橫向擴展
- 注入的協議的可配置型,基於XML的描述,可實現很方便的修改和維護
- 結合“接口加實現”的服務模式,可以快速整合各個模塊的資源,實現了有效的“服務化”
模塊擴展移除時如何將他的注入信息也一同移除?完整代碼:




11. OSGI.NET 高級話題
11.1 OSGI.NET 的環境支持(官網文檔):
- 支持控制台應用程序。
- 支持Windows窗體應用程序。
- 支持WPF應用程序。
- 支持Windows服務應用程序。
- 支持ASP.NET應用程序。
- 支持Windows Mobile應用程序。
- 支持UIOSP平台嵌套。
OSGi.NET是基於.NET框架且與語言以及類型無關,也就是說.NET能支持什么環境,OSGi.NET也就能支持什么環境,他能適應各種.NET生產和裝配環境。
11.2 OSGI.NET 的設計原則與最佳實踐
- 盡量邏輯隔離,物理隔離。邏輯隔離是必須的,低耦合、高內聚,物理隔離是最好的,可替換
- 盡量以“接口+實現”的方式來處理邏輯依賴,各模塊之間的依賴越小越好
- 盡量把接口和實現的邏輯放在不同的模塊中,結合動態性實現可維護、可更新
- 盡量以“擴展點和擴展”的方式處理模塊之間的資源依賴,比如UI上的圖標等盡量將共享的程序集放在一個共享模塊中,避免重復依賴和版本混亂,也可減小模塊體積
- 盡量不要在“激活器(Activator)”的start函數中調用服務實現,避免因模塊啟動順序導致服務可能為空。其他地方如有需要盡量用
- UIShell.OSGi.ServiceTracker<T>來處理
- 盡量對具有邏輯或資源依賴的模塊的關鍵生命周期狀態進行相應的處理,比如安裝,停止,卸載等,即所謂的“保持系統動態性”
- 盡量依賴另一模塊的共享程序集而非整個模塊,可有更快的加載速度
- 盡量將已有的模塊封裝打包到一個統一的部署平台,利於共享、測試、發布
UIOSP 官網:http://www.iopenworks.com/
OSGI.NET 官網:http://osgi.codeplex.com/
參考資料:http://www.cnblogs.com/zhaojudi/archive/2013/02/26/2933788.html
http://www.cnblogs.com/shalahu/archive/2013/02/21/2921306.html
示例源碼: http://osgi.codeplex.com/SourceControl/latest
