您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)OSGi全面總結(jié)與WebSphere應(yīng)用范例是怎樣的,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
為了解決現(xiàn)實(shí)工程中遇到的版本沖突問題,我研究了 OSGi 技術(shù)。為此,我在網(wǎng)上搜索了很多的有關(guān)于 OSGi 的文章,但是最后發(fā)現(xiàn)很少有人能清楚的闡述 OSGi 的由來和 OSGi 最本質(zhì)的特性,直到我發(fā)現(xiàn) Neil Bartlett 的 OSGi In Practice。它讓理解了 OSGi 的本質(zhì),從而清楚的明白:解決 Java 工程中的版本沖突問題,OSGi 是最好的選擇。這是由 OSGi 的本質(zhì)決定的,這也是為什么大的 Java 軟件產(chǎn)品紛紛開始采用 OSGi 框架的原因。Java 有天生的缺陷,而 OSGi 彌補(bǔ)了它。然后我又花了大量的時(shí)間來研究 WebSphere Application Server 是如何支持 OSGi 的,最后才能成功的使我的應(yīng)用支持 OSGi,從而解決了版本沖突問題。
OSGi 的由來
隨著科技和需求的發(fā)展和變化,現(xiàn)在的軟件變得越來越龐大。這樣,隨之而來的最大挑戰(zhàn)就是軟件在設(shè)計(jì)上的越來越復(fù)雜和維護(hù)上的越來越困難。為了解決這個(gè)問題,軟件架構(gòu)師將軟件切分成比較小的并且易于理解的多個(gè)模塊。那么軟件模塊化會給我們帶來什么樣的好處呢?
拆分人力:將軟件模塊化后,我們就可以分配獨(dú)立的團(tuán)隊(duì)去處理獨(dú)立的模塊,從而將人力拆分開來。這樣既便于管理,又會降低整個(gè)軟件的設(shè)計(jì)的復(fù)雜性。因?yàn)槊總€(gè)獨(dú)立的團(tuán)隊(duì)可以專心去設(shè)計(jì)和實(shí)現(xiàn)其模塊,而不用通盤考慮整個(gè)軟件的復(fù)雜性。
抽象化:將軟件模塊化后,我們將整個(gè)軟件抽象化成多層、多 模塊的一個(gè)集成。這樣使整個(gè)軟件易于理解,便于管理。
重用:將軟件模塊化后,每個(gè)模塊有其獨(dú)立的功能和封裝。這樣這個(gè)模塊就可以在多處(甚至是將來其他的軟件中)重用,從而節(jié)省人力。
易于維護(hù):將軟件模塊化后,當(dāng)軟件出現(xiàn)問題后,我們可以容易地定位問題出在那個(gè)模塊,而每個(gè)模塊又相對較小和易于理解,從而降低了軟件維護(hù)的難度。
基于上述的 4 個(gè)優(yōu)點(diǎn),在當(dāng)前的軟件設(shè)計(jì)中,軟件模塊化是軟件架構(gòu)師的主流思想。為了實(shí)現(xiàn)軟件模塊化,應(yīng)運(yùn)而生的就是面向?qū)ο蟮母呒壘幊陶Z言,Java 是其中的典型代表。Java 用其獨(dú)有的 Jar 格式文件去包裝 Java 類和其他的資源文件,從而可以將軟件組件封裝成獨(dú)立的 Jar 文件。這些 Jar 文件可以相互依賴并共同完成同一個(gè)工作,從而實(shí)現(xiàn)了軟件的模塊化。但是 Java 卻不能真正的帶給我們軟件模塊化的那 4 個(gè)優(yōu)點(diǎn),為什么呢?為了解釋這個(gè)問題,我們需要知道模塊的定義。
什么是一個(gè)模塊?
一個(gè)模塊應(yīng)該有以下 3 個(gè)特性:
自包含:一個(gè)模塊應(yīng)該是一個(gè)業(yè)務(wù)邏輯的整體。它應(yīng)該可以作為一個(gè)獨(dú)立的整體被移動(dòng)、安裝和卸載。模塊不是一個(gè)原子體,它可以包含多個(gè)更小的部分,但這些部分不能獨(dú)立存在。
高內(nèi)聚:一個(gè)模塊不應(yīng)該做很多不相關(guān)的事情,它應(yīng)該專注于 1 個(gè)業(yè)務(wù)邏輯的目標(biāo)并盡全力實(shí)現(xiàn)這個(gè)目標(biāo)。
低耦合:一個(gè)模塊不應(yīng)該關(guān)注其他模塊的內(nèi)部實(shí)現(xiàn),松散的聯(lián)系允許我們?nèi)ジ哪硞€(gè)特定的模塊,而不會影響到其他的模塊。
而 Java 語言的 Jar 文件并不能完美的實(shí)現(xiàn)一個(gè)模塊這 3 個(gè)特性,它主要會遇到以下的 3 個(gè)問題:
針對一個(gè) Jar 文件,沒有對應(yīng)的 Java 運(yùn)行時(shí)的概念。Jar 文件只有在開發(fā)和部署的時(shí)候有意義,而在 JVM 中,所有的 Jar 文件中的內(nèi)容被簡單地聯(lián)系在一起作為一個(gè)單獨(dú)的全局的列表,這就是所謂的“Classpath”。這種類加載模式,使 Jar 文件在運(yùn)行時(shí)是不可見的。
Jar 文件沒有標(biāo)準(zhǔn)的元數(shù)據(jù)信息去指明該 Jar 文件所需要的外部依賴文件列表,這樣我們就不能清楚的知道,該 Jar 文件需要和其他的那些 Jar 文件一起工作。另外,現(xiàn)在的 Jar 文件沒有版本信息,這樣,同一 Jar 文件的多個(gè)版本就不能同時(shí)被加載。
Java 沒有機(jī)制在不同的 Jar 文件中隱藏信息。
這 3 個(gè)問題,使 Jar 文件在模塊的“自包含”和“低耦合”這兩個(gè)特性上做的不好,從而使 Java 在模塊的“拆分人力”和“易于維護(hù)”這兩個(gè)優(yōu)點(diǎn)上沒有好的表現(xiàn),而更嚴(yán)重的是第 2 個(gè)問題,這使 Java 應(yīng)用軟件存在難以處理的版本沖突問題。
Java 語言為了安全的考慮,它的類加載器(注意不是類加載)是多層立體的并且對其類加載采用了父委托機(jī)制。并且,當(dāng)同一個(gè)類加載器加載類文件時(shí),JVM 會加載最先發(fā)現(xiàn)類。所以當(dāng)同一個(gè)類的新舊兩個(gè)版本被分別封裝在兩個(gè)不同的 jar 文件中(比如:ClassVersion2.jar 和 ClassVersion1.jar),而這兩個(gè) jar 文件又都在 JVM 的類加載路徑里的話,最先被加載的 Jar 文件中的類才會被使用到。而現(xiàn)在的 Java 應(yīng)用軟件因?yàn)殚L時(shí)間的更新維護(hù),同一個(gè)模塊的多個(gè)版本共存的情況比比皆是,這就會產(chǎn)生版本沖突問題。比如說,在 Java 應(yīng)用軟件中存在一個(gè)模塊 ThirdComponent,這個(gè)模塊依賴 ClassVersion 模塊而且必須同老版本的 ClassVersion 模塊(ClassVersion1.jar)一起工作,當(dāng)新 ClassVersion 模塊(ClassVersion2.jar)被升級到軟件中后,ThirdComponent 模塊很有可能就不會工作,因?yàn)轭惣虞d器很有可能會先加載的是 ClassVersion2.jar,而不是 ClassVersion1.jar。其實(shí)產(chǎn)生這個(gè)問題的根本原因是,Java 的 Jar 文件在自包含上做的不好。Jar 文件只是在軟件的封裝上起到了作用,而在 JVM 運(yùn)行時(shí)中,Java 只關(guān)心類而忽略了 Jar,從而使 Java 的類加載變成了平面的線性的而非立體的網(wǎng)狀的。
為了解決 Java 在模塊化中存在的問題,OSGi 模塊系統(tǒng)出現(xiàn)了。OSGi 是基于 Java 之上開發(fā)的,它提供了一種建立模塊化的 Java 應(yīng)用程序的方法并定義了這些模塊在運(yùn)行時(shí)中如何相互交互。
OSGi 最本質(zhì)的特性
OSGi 是一個(gè)由大概 40 個(gè)公司組成的聯(lián)盟來共同定義的一個(gè)標(biāo)準(zhǔn)。依照這個(gè)標(biāo)準(zhǔn),目前,有 4 種獨(dú)立實(shí)現(xiàn)了的 OSGi 框架,他們分別是:
Equinox: 這個(gè) OSGi 框架是目前應(yīng)用最廣泛的 OSGi 框架。它是由 IBM 開發(fā)的,目前已經(jīng)被應(yīng)用到 Eclipse,Lotus Notes,IBM WebSphere Application Server 等等。Equinox 實(shí)現(xiàn)了版本為 4.1 的 OSGi 規(guī)范。
Felix:這個(gè) OSGi 框架實(shí)現(xiàn)了版本 4.x 的 OSGi 規(guī)范,它是由 Apache 開發(fā)和維護(hù)的。
Knopflerfish:這是一個(gè)流行并成熟的實(shí)現(xiàn)了版本 3 和 4.1 的 OSGi 規(guī)范的 OSGi 框架。它是由 Makewave AB 開發(fā)和維護(hù)的。
Concierge:這個(gè) OSGi 框架實(shí)現(xiàn)了版本 3 的 OSGi 規(guī)范。
關(guān)于 OSGi 這個(gè)名字,2 個(gè)最常被問到的問題是 OSGi 代表什么?為什么 i 是小寫的?
關(guān)于這兩個(gè)問題,權(quán)威性的回答是:官方上 OSGi 不代表任何東西,然而,通常上說 OSGi 代表“Open Service Gateway initiative. 而小寫字母“i”來自單詞“initiative”。
至于 OSGi 的中心思想,它非常地簡單。傳統(tǒng) Java 軟件問題的根源就是全局的扁平的類加載路徑(Classpath),所以 OSGi 采用了一種完全不同的類加載機(jī)制,那就是每個(gè)模塊都有其獨(dú)立的類加載路徑。這幾乎解決了傳統(tǒng) Java 在模塊化中遇到的所有問題,然而一個(gè)新的問題又產(chǎn)生了,軟件中的模塊是要在一起工作的,這就意味著不同的模塊之間存在類共享(不然的話,一個(gè)模塊如何能夠調(diào)用到另外一個(gè)模塊呢),如果每個(gè)模塊有一個(gè)類加載路徑,模塊間的類共享如何解決?為了解決這個(gè)問題,OSGi 定義了一個(gè)特殊的并完善的類共享機(jī)制。OSGi 將會采用顯示的導(dǎo)入和導(dǎo)出機(jī)制來控制模塊間的類共享。
在 OSGi 中,模塊被起了另外一個(gè)名字,叫做 bundle。實(shí)際上 OSGi 的 bundle 就是一個(gè) Java 的 Jar 文件。OSGi 并沒有定義一個(gè)新的標(biāo)準(zhǔn)去封裝 Java 類和其他的資源文件,標(biāo)準(zhǔn) Jar 文件可以很好地工作在 Java 應(yīng)用軟件中。在 OSGi 體系里,只是一些新的元數(shù)據(jù)信息被加入到 Jar 文件中,這些元數(shù)據(jù)信息使的 Jar 文件變成一個(gè) OSGi 體系中的 bundle。那么什么樣的元數(shù)據(jù)信息被加入進(jìn)來了呢?
Bundle 的名字。OSGi 提供了一個(gè)“symbolic”名字作為這個(gè) bundle 的唯一標(biāo)識符。
Bundle 的版本信息。
Import 和 export 列表。從這個(gè)列表,我們可以清楚地知道這個(gè) OSGi bundle 需要導(dǎo)入和導(dǎo)出那些包的類。導(dǎo)入的包是本 bundle 需要用到的外部資源,導(dǎo)出的包是其他 bundle 可以用的本 bundle 中的資源。
Bundle 需要運(yùn)行的最小的 Java 版本。這個(gè)信息是可選的。
種類繁雜的人類可讀的其他信息,比如說:本 bundle 的提供者,版權(quán)陳述,聯(lián)系地址等等。
這些元數(shù)據(jù)信息被放到 Jar 文件的 MANIFEST.MF 文件中,而這個(gè)文件是每個(gè)標(biāo)準(zhǔn) Jar 文件的一部分。用一個(gè)標(biāo)準(zhǔn)的 Jar 文件作為 OSGi bundle 的一個(gè)好處是 bundle 可以被用在 Jar 文件可以出現(xiàn)的任何一個(gè)地方,因?yàn)?bundle 就是一個(gè)純粹的 Jar 文件。當(dāng)一個(gè) bundle 用在 OSGi 的運(yùn)行時(shí)之外的時(shí)候,這些額外多出來的元數(shù)據(jù)信息會被 Java 運(yùn)行時(shí)簡單地忽略掉,所以說,bundle 是向前兼容的。那么除了這個(gè),OSGi 的 bundle 還給我們帶來了什么樣的好處呢?
為每一個(gè) bundle 提供一個(gè)類加載路徑意味著什么呢?簡單地說我們?yōu)槊恳粋€(gè) bundle 提供了一個(gè)類加載器,這個(gè)類加載器能夠看到這個(gè) bundle 文件里的類和其他資源文件。但是為了達(dá)到多個(gè) bundle 共同工作的目的,在 OSGi 的類加載器之間,類加載請求可以從一個(gè) bundle 的類加載器被委托到另外一個(gè) bundle 的類加載器?;叵胍幌略跇?biāo)準(zhǔn) Java 和 J2EE 中,類加載器是一個(gè)樹形結(jié)構(gòu)的,類加載請求總是被向上委托給每一個(gè)類加載器的父親。這中類加載機(jī)制不允許在水平的樹節(jié)點(diǎn)之間進(jìn)行類加載委托。為了讓一個(gè)類庫可以被類加載器樹的多個(gè)樹枝共同所見,我們就需要將這個(gè)類庫推到這些樹枝共同的祖先節(jié)點(diǎn)。這樣這個(gè)版本的類庫就會被這些樹枝上的所有節(jié)點(diǎn)所見,而不管是否這些節(jié)點(diǎn)都想看到這個(gè)版本的類庫。圖 1 是一個(gè)典型的 J2EE 類加載器層次結(jié)構(gòu),它展示了為什么類庫會不斷推高的原因。
圖 1. 典型的 J2EE 類加載器層次結(jié)構(gòu)
而樹型結(jié)構(gòu)并不是我們需要的,我們真正需要的是網(wǎng)狀結(jié)構(gòu)。兩個(gè)組件之間的依賴關(guān)系不是簡單的上下級的關(guān)系,而應(yīng)該是一種提供者和使用者的網(wǎng)絡(luò)關(guān)系。類的加載請求被從一個(gè) bundle 的類加載器委托到另外一個(gè) bundle 的類加載器,而這種委托是基于 bundle 之間的這種網(wǎng)狀的依賴關(guān)系。圖 2 給了我們一個(gè) OSGi 中 bundle 之間的網(wǎng)狀的依賴關(guān)系的例子。
圖 2. OSGi 中 bundle 之間的網(wǎng)狀的依賴關(guān)系
在 OSGi 中,bundle 之間的依賴關(guān)系是通過顯示的 import 和 export 類包列表來決定的。比如說,在圖 2 的 bundle B 中包含一個(gè)類包,名字為 com.ibm.bundle.b.somePackage.。Bundle b 就可以選擇在它的 MANIFEST.MF 文件去 export 這個(gè)類包。而 bundle A 也可以選擇去在它的 MANIFEST.MF 文件中 import 類包 com.ibm.bundle.b.somePackage。然后在 OSGi 運(yùn)行時(shí)中,OSGi 框架將負(fù)責(zé)匹配不同 bundle 的 import 和 export 列表。而這個(gè)匹配過程被稱為 OSGi 的解決過程(resolution process)。OSGi 的解決過程是相當(dāng)復(fù)雜的,但是這個(gè)過程是被 OSGi 框架實(shí)現(xiàn)了的,不需要每個(gè) bundle 自己來關(guān)心它。每個(gè) bundle 只需要寫一些很簡單的 import 和 export 聲明語句在各自的 MANIFEST.MF 文件里。一旦 OSGi 框架匹配了 bundle A 的 import 列表里的類包 com.ibm.bundle.b.somePackage 與 bundle B 的 export 列表里的類包 com.ibm.bundle.b.somePackage,那么這兩個(gè) bundle 就會被連接在一起,而這就意味著當(dāng) bundle A 需要載入任何類包 com.ibm.bundle.b.somePackage 里的類時(shí),這個(gè)類載入請求就會被委托給 bundle B 的類載入器,而 bundle B 的類載入器將會載入這個(gè)類,并將類實(shí)例傳給 bundle A。而因?yàn)?bundle A 依賴 bundle B 和 bundle C, 如果 bundle A import 列表里的所有類包都能在 bundle B 和 bundle C 的 export 列表里發(fā)現(xiàn),那么 bundle A 將會被稱為解決成功,它會進(jìn)入解決了狀態(tài)(resolved)。如果 bundle A 的 import 列表里需要的某些類包沒有在 bundle B 和 bundle C 的 export 列表里發(fā)現(xiàn),那么 bundle A 的解決就沒有成功,bundle A 將不能被使用和啟動(dòng)。由此可見,OSGi 中,bundle 之間的依賴關(guān)系是通過顯示的 import 和 export 列表來決定的。
隱藏了 bundle 中的信息。
因?yàn)樵?OSGi 中,bundle 之間的依賴關(guān)系是通過顯示的 import 和 export 列表來決定的,所以我們沒有必要 export 一個(gè) bundle 中的所有的類包,進(jìn)而能起到隱藏 bundle 中信息的作用。在 OSGi 中,只有那些被顯示的 export 出來的類包才能被其他的 bundle import。
增加了版本控制并允許多版本并存。
OSGi 不僅僅使 bundle 之間通過類包名相互依賴,它還可以為類包加入版本信息。這是我們能夠應(yīng)付 bundle 的版本變化問題。Export 的類包也可以攜帶一個(gè)版本信息,而 import 卻可以引用一個(gè)版本范圍內(nèi)的所有類包,這讓我們的 bundle 可以依賴一個(gè)版本范圍內(nèi)的所有類包。于是說,在 OSGi 中,同一 bundle 的多個(gè)版本就可以同時(shí)存在。在本文的第三章,我將詳細(xì)介紹,OSGi 是如何允許同一個(gè) bundle 的多個(gè)版本并行存在,進(jìn)而客服了 Java 應(yīng)用軟件中組件的版本沖突問題
解釋 OSGi 是如果克服版本沖突問題的
OSGi 之所以能夠解決 Java 應(yīng)用軟件中組件的版本沖突問題,原因就是 OSGi 的網(wǎng)狀類加載器和 OSGi bundle 的版本信息控制。為什么這么說呢?
OSGi 的網(wǎng)狀類加載器架構(gòu)使每個(gè) OSGi bundle 都擁有一個(gè)獨(dú)立的類加載器,而 bundle 只是一個(gè)標(biāo)準(zhǔn) Jar 文件。這樣,對同一個(gè) bundle 的不同版本,我們就可以創(chuàng)建多個(gè)不同的 Jar 文件。這些 Jar 文件的實(shí)際內(nèi)容可以完全一樣,而只是文件名不同(甚至文件名都可以相同,因?yàn)樵?OSGi 框架中,bundle 名和版本的組合才是唯一標(biāo)識符)。因此這些 Jar 文件,在 OSGi 框架看來,是不同的 bundle,于是同一個(gè)組件的不同版本可以被同時(shí)載入到 JVM 中,這就解決了 Java 應(yīng)用軟件中同一組件不同版本的并存問題,接下來只要解決版本辨識問題,那么 Java 應(yīng)用軟件中組件的版本沖突問題就會被客服掉了。
OSGi 添加了版本控制信息來區(qū)分同一個(gè) bundle 的不同版本,而且在 OSGi 框架中 bundle 名和 bundle 版本的組合才是這個(gè) bundle 的唯一標(biāo)識符,于是通過 bundle 的版本控制,同一個(gè) bundle 的不同版本就可以得到區(qū)分,而 bundle 直接的依賴關(guān)系也可以通過版本來加以限制,從而就能完美的解決 Java 應(yīng)用軟件中組件的版本沖突問題了。
那么 OSGi 是如何進(jìn)行版本控制的呢?
OSGi 通過在 MANIFEST.MF 文件中添加 Bundle-Version 屬性來個(gè)為每一個(gè) bundle 添加一個(gè)版本信息,而且這個(gè)版本信息必須嚴(yán)格遵循:3 數(shù)字段 +1 字符段的格式,6.2.0.beta_3 是一個(gè)典型有效的 bundle 版本信息。這前面的 3 個(gè)數(shù)字段就是大家都知道的主版本,小版本和微版本,而那個(gè)最后的字母段則是校正段。當(dāng)前面的 3 個(gè)任意一個(gè)數(shù)字段沒有值時(shí),OSGi 將會隱式地將 0 付給這個(gè)字段,所以版本 1 是和 1.0、1.0.0 相同的。而如果沒給 bundle 指定任意一個(gè)版本,那么 0.0.0 將被認(rèn)為是這個(gè) bundle 的版本信息。
另外 OSGi 中,版本的比較是采用從前到后的比較方式。如果在版本比較時(shí),第一個(gè)數(shù)字段就不同,那么后面的 3 個(gè)字段就不用比較了,因?yàn)?OSGi 的前一個(gè)版本段是后面所有字段值的總和,所以大版本就不相同的時(shí)候,后面的小版本就不需要比較了,比如說:2.0.0 是大于 1.999.999。而如果兩個(gè) bundle 的版本信息,在前面的 3 個(gè)數(shù)字段都相同的時(shí)候,OSGi 就會對最后的字母段進(jìn)行比較。而最后的字母段可以包含大寫或小寫的字母 A 到 Z、數(shù)字、連接線和下劃線,所以它的比較比較復(fù)雜。OSGi 采用了標(biāo)準(zhǔn) Java String 類的 compareTo() 方法的算法來進(jìn)行比較,而標(biāo)準(zhǔn) Java 的 String 類的 compareTo() 方法會對校正段的每一個(gè)字母按順序進(jìn)行比較,直到出現(xiàn)差異。另外如果字母相同,那么短的那個(gè)校正段的值將被認(rèn)為小于長的校正段,beta_01 將會比 beta_010 小。
最后需要提的是 OSGi 不但可以為 bundle 指定一個(gè)版本信息,還可以為每一個(gè)類包指定一個(gè)版本信息,即 bundle 的版本控制是可以做到類包級別的(而且這是推薦的 OSGi 版本控制方式)。當(dāng) bundle 在 export 類包時(shí),用戶可以為每個(gè)類包指定一個(gè)版本信息。而當(dāng) bundle 需要 import 某特定版本的類包時(shí),用戶除了可以指定一個(gè)特定的版本信息外,還可以指定一個(gè)版本信息范圍。而這個(gè)范圍可以用方括號“【”和圓括號“(”來作為邊界,方括號“【”表示邊界值也在范圍之內(nèi),而圓括號“(”則相反 . 比如說【 1.0.0,2.0.0)表示從版本 1.0.0 開始到 2.0.0 之間的所有的小版本,2.0.0 不在這個(gè)范圍只內(nèi)。下面是一些進(jìn)一步的范圍列表的例子,在下面的表 1 中 x 代表有效的范圍列表:
表 1. 版本范圍舉例
樣例 | 版本范圍 |
---|---|
[1.2.3,4.5.6) | 1.2.3<=x<4.5.6 |
[1.2.3,4.5.6] | 1.2.3<=x<=4.5.6 |
(1.2.3,4.5.6) | 1.2.3<x<4.5.6 |
(1.2.3,4.5.6] | 1.2.3<x<=4.5.6 |
[1.2.3,1.2.3] | 1.2.3 |
1.2.3 | 1.2.3<=x |
0.0.0<=x |
解釋 WAS 在引入 OSGi 之后的類載入機(jī)制
OSGi 是如此優(yōu)秀的一個(gè)框架,因此很多 Java 應(yīng)用軟件開始采用它,WebSphere Application Server(WAS)作為 IBM 最中要的 J2EE 服務(wù)器從版本 6.1 開始采用 OSGi 框架,因此當(dāng)你的應(yīng)用是基于 WAS 的并遇到了版本沖突問題,你就可以將你的應(yīng)用轉(zhuǎn)換成 OSGi 的 bundle,從而解決版本沖突問題。在將你的 WAS 的應(yīng)用轉(zhuǎn)變成 OSGi 的 bundle 之前,我們需要了解 WAS 是如何支持 OSGi 的,進(jìn)而采取相應(yīng)的行動(dòng)。
圖 3. WAS 從 6.1 以后的類加載器層次結(jié)構(gòu)
圖 3 是 WAS 從版本 6.1 以后的類加載器層次結(jié)構(gòu),從此圖,我們可以知道 WAS 并不是完全采用 OSGi 框架(可能是出于向前兼容等因素考慮),IBM 只是將 WAS 的一部分變成了 OSGi 框架的類加載模式,而其他的部分繼續(xù)延續(xù)了以前版本的類加載器層 次結(jié)構(gòu)。而 WAS 中 OSGi 的那部分類加載器,以網(wǎng)關(guān)的形式與 WAS 的擴(kuò)展類加載器連接在一起。
接下來,大家可能奇怪,WAS 原有的類加載器是如何同 WAS 中的 OSGi 部分的類加載器一起工作的呢? WAS 將如何進(jìn)行類加載呢?
為了解釋這個(gè)問題,我們首先要清楚,WAS 中的那一部分采用了 OSGi 的框架? WAS 將其常用的重要的插件部分做成了 OSGi,而所有的這些插件被放置在 WAS 的 plugins 目錄中,因此 plugins 目錄下的所有的插件是以 OSGi bundle 的形式被載入到 WAS 中來的。接下來,我將解釋從版本 6.1 以后 WAS 將如何進(jìn)行類加載。從圖 3,我們可以得知,WAS 的 OSGi 框架是與 Ext 類加載器連接在一起的,這就是說 WAS 的 OSGi 框架在 WAS 整體的類加載器中處于一個(gè)很高的層次。而 Java 的類加載是采用父委托機(jī)制的,這就使普通的 WAS 上的應(yīng)用程序會一層層的向上請求加載類,這樣當(dāng)某個(gè)特定的類在 WAS 的 OSGi 部分中被發(fā)現(xiàn),那么 WAS 的類加載委托就會進(jìn)入到 WAS 的 OSGi 運(yùn)行時(shí)中。這樣當(dāng)這個(gè)類加載以后,而它又需要加載其他類時(shí),這之后的類加載委托請求就會在 WAS 的 OSGi 運(yùn)行時(shí)中相互傳遞。
由此可見,如果我們需要將自己的 WAS 上的應(yīng)用程序轉(zhuǎn)變成支持 OSGi,我們則需要將這個(gè)應(yīng)用程序的模塊轉(zhuǎn)變成 OSGi bundle,然后將其放置在 WAS 的 plugins 目錄下。
介紹一個(gè)具有版本沖突問題的 WAS 上的樣例程序
在本章,我會模擬一個(gè) WAS 上版本沖突的問題,讓大家能清楚地看到這種版本沖突問題是如何出現(xiàn)的。然后在第六章,我會告訴大家如何將這個(gè)樣例程序的某些組件轉(zhuǎn)變成 bundle,從而解決了版本沖突問題。
為了說明問題,我構(gòu)建如下一個(gè)郵件系統(tǒng),這個(gè)系統(tǒng)可以閱讀各種各樣類型的郵件。因?yàn)猷]件的類型可以存在很多種,而且每一種的郵件可以使用獨(dú)特的瀏覽方式,為了設(shè)計(jì)和維護(hù)的簡單,我們將它拆分成多個(gè)模塊。我們將各種郵件類型共用的接口和基礎(chǔ)類拆分成一個(gè)模塊,而將每種不同的郵件類型拆分成各自獨(dú)立的模塊。而為了便于描述將來會出現(xiàn)的版本沖突問題,我們只是用兩種簡單的硬編碼的郵件類型(FixedMailbox 和 XMLMailbox)來說明這個(gè)系統(tǒng)的整體結(jié)構(gòu),請看圖 4。
圖 4. 郵件系統(tǒng)結(jié)構(gòu)圖
這個(gè)結(jié)構(gòu)圖能夠清晰得告訴我們,整個(gè)系統(tǒng)的通用接口和基礎(chǔ)類被封裝在 MailboxAPI 模塊中,而每個(gè)具體的郵件類型將分別是一個(gè)模塊(FixedMailbox 模塊和 XMLMailbox 模塊),這些模塊將實(shí)現(xiàn)這些通用接口和每種郵件類型各自的業(yè)務(wù)邏輯,然后將郵件展示給用戶瀏覽。所以在這個(gè)圖中將最少有 3 個(gè)模塊,他們會由不同的團(tuán)隊(duì)來分別負(fù)責(zé)。當(dāng)整個(gè)系統(tǒng)開發(fā)完畢之后,各個(gè)團(tuán)隊(duì)需要將各自的組件發(fā)布到運(yùn)行環(huán)境當(dāng)中。因?yàn)?MailboxAPI 模塊(MailboxAPI.jar)是被所有的其他組件所依賴的,為了將來維護(hù)和發(fā)布的方便,一般 MailboxAPI.jar 會被放置到 WAS 的 lib 目錄下,這樣,其他的每一個(gè)組件都能輕松的找到它,而 MailboxAPI 模塊團(tuán)隊(duì)也可以輕松地發(fā)布和維護(hù) MailboxAPI,因?yàn)榘l(fā)布位置的唯一,MailboxAPI 模塊的每一次發(fā)布和維護(hù)將不需要通知到所有其他的團(tuán)隊(duì)。而其他的模塊,因?yàn)榘瑯I(yè)務(wù)邏輯和展示層,他們一般都是一個(gè) ear 文件,所以他們的發(fā)布位置明顯是與 MailboxAPI.jar 不同的。圖 5 和圖 6 展示給我們 FixedMailbox 和 XMLMailbox 正常運(yùn)行后的樣子。
圖 5. FixedMailbox 的運(yùn)行情況
圖 6. XMLMailbox 的運(yùn)行情況
OSGi與Spring DM:使用Spring DataSource
2009甲骨文全球大會:OSGi將獲得更多支持
打造一個(gè)Hello World OSGi Web應(yīng)用程序
部署并運(yùn)行你的OSGi Web應(yīng)用程序
OSGi近況總結(jié):用戶群蓬勃發(fā)展
為了方便大家的學(xué)習(xí),我將已經(jīng)開發(fā)好的這 3 個(gè)模塊以附件的形式附在本文上,它們在壓縮文件 Version1.zip 里。你只需要解壓縮它,然后將 MailboxAPI.jar 放置在 WAS 的 lib 目錄下,然后啟動(dòng)你的 WAS 系統(tǒng),接著你需要安裝 FixedMailboxReaderEAR.ear 和 XMLMailboxReaderEAR.ear(他們分別代表 FixedMailbox 模塊和 XMLMailbox 模塊)。在 Version1.zip 你還會發(fā)現(xiàn) FixedMailbox.jar 和 XMLMailbox.jar,它們分別是模塊 FixedMailbox 和 XMLMailbox 的業(yè)務(wù)邏輯,而 FixedMailboxReaderEAR.ear 和 XMLMailboxReaderEAR.ear 是這兩個(gè)模塊的最后封裝。
注意:附件里的每一個(gè)文件里,都含有源碼,以方便感興趣的讀者深入研究。
在整個(gè)郵件系統(tǒng)運(yùn)行一段時(shí)間后,某些用戶較多的個(gè)別郵件模塊就可能面臨著升級。因?yàn)榭蛻舳?,需求就多,而用戶的需求又是千奇百怪的,必然會出現(xiàn)某個(gè)特定的需求波及到了基礎(chǔ)模塊 MailboxAPI。這個(gè)時(shí)候,就可能會出現(xiàn)如下的情況:模塊 MailboxAPI 和 XMLMailbox 被要求升級,而模塊 FixedMailbox 為了穩(wěn)定,要求不產(chǎn)生任何變化。然而當(dāng) XMLMailbox 的需求很大時(shí),可能使 MailboxAPI 也產(chǎn)生了很大的變化,從而影響了 FixedMailbox,使之不能正常工作,于是版本沖突問題產(chǎn)生了。
為了演示這個(gè)問題,我改變了模塊 MailboxAPI 和 XMLMailbox 的代碼,產(chǎn)生了版本 2.0 的 MailboxAPI 和 XMLMailbox 模塊,他們被放置在附件 2(Version2.zip)中。為了看到真實(shí)的版本沖突問題,請解壓縮 Version2.zip,然后停止 WAS 并刪除 WAS 的 lib 目錄下的 MailboxAPI.jar,接著將 MailboxAPI2.jar 放置在 WAS 的 lib 目錄下,然后重啟你的 WAS 系統(tǒng),接著你需要用 XMLMailboxReaderEAR2.ear 去升級已經(jīng)存在的 XMLMailboxReader 應(yīng)用,然后分別訪問兩個(gè)模塊的 Servlet,你就會看到 FixedMailbox 模塊將不能正常工作,而 XMLMailbox 則一切正常,如圖 7 或圖 8 所示。
圖 7. FixedMailbox 不能正常運(yùn)行
圖 8. XMLMailbox 可以運(yùn)行
注意:如果你不刪除 MailboxAPI.jar,而是讓 MailboxAPI.jar 和 MailboxAPI2.jar 并存在 WAS 的 lib 目錄下,那么就有可能是 FixedMailbox 能正常工作,而 XMLMailbox 不能正常工作,如圖 9 和圖 10 所示,原因是 MailboxAPI.jar 可能在 MailboxAPI2.jar 之前被載入到類加載器中了。總之,F(xiàn)ixedMailbox 和 XMLMailbox 將不能同時(shí)工作,這就是版本沖突問題。
圖 9. 當(dāng) MailboxAPI.jar 和 MailboxAPI2.jar 并存時(shí),F(xiàn)ixedMailbox 可以正常運(yùn)行
圖 10. 當(dāng) MailboxAPI.jar 和 MailboxAPI2.jar 并存時(shí),XMLMailbox 不能運(yùn)行
講述如何將這個(gè)樣例程序中的某些組件轉(zhuǎn)變成 WAS 上的 OSGi bundle,從而解決了版本沖突問題
為了解決在第五章中的版本沖突問題,我們只需要將模塊 FixedMailbox 和 XMLMailbox 的業(yè)務(wù)邏輯部分(FixedMailbox.jar 和 XMLMailbox.jar)轉(zhuǎn)變成 OSGi 的 bundle,然后將 MailboxAPI 的版本 1 和版本 2(MailboxAPI.jar 和 MailboxAPI2.jar)也都轉(zhuǎn)變成 bundle,并使 FixedMailbox.jar 依賴于 MailboxAPI.jar,使 XMLMailbox.jar 依賴于 MailboxAPI2.jar。接下來,將 WAS 的 lib 目錄下的 MailboxAPI 模塊移除掉,然后將 FixedMailbox.jar、XMLMailbox.jar、MailboxAPI.jar 和 MailboxAPI2.jar 同時(shí)放入 WAS 的 plugins 目錄下,最后重新啟動(dòng) WAS,你會發(fā)現(xiàn)模塊 FixedMailbox 和 XMLMailbox 能同時(shí)工作,如圖 11 和圖 12 所示。
圖 11. 在將 FixedMailbox.jar 轉(zhuǎn)變?yōu)?bundle 后,F(xiàn)ixedMailbox 可以正常運(yùn)行
圖 12. 在將 XMLMailbox.jar 轉(zhuǎn)變?yōu)?bundle 后,XMLMailbox 可以正常運(yùn)行
在將整個(gè)郵件系統(tǒng)轉(zhuǎn)變成支持 OSGi bundle 后,會使郵件系統(tǒng)的各個(gè)模塊之間的依賴關(guān)系從圖 4 編程圖 13 的情況,因?yàn)樵?OSGi 中,同一模塊的多個(gè)版本可以并存,并且模塊之間的依賴關(guān)系可以通過版本進(jìn)行限制,從而是 Java 應(yīng)用軟件中的版本沖突問題得到了完美的解決。
圖 13. 最后的郵件系統(tǒng)的模塊之間的依賴關(guān)系
將已有的 Jar 文件轉(zhuǎn)換成 bundle 非常簡單,我們不需要改變?nèi)魏?Java 代碼,只需要將必要的 OSGi 的 bundle 信息加入 Jar 文件的 MANIFEST.MF。為了方便大家的查看,我將已經(jīng)轉(zhuǎn)好的 bundle 文件 FixedMailbox.jar、XMLMailbox.jar、MailboxAPI.jar 和 MailboxAPI2.jar 做成了附件 3。
OSGi 框架是實(shí)現(xiàn) Java 應(yīng)用軟件模塊化的重要手段。當(dāng)前,OSGi 已經(jīng)變的非常流行,很多的著名的 Java 應(yīng)用在底層已經(jīng)開始采用 OSGi 框架,比如說 Spring,IBM 的 Eclipse 和 WebSphere Application Server。
以上就是OSGi全面總結(jié)與WebSphere應(yīng)用范例是怎樣的,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。