osgi导出包和非导出包_了解如何解决OSGI捆绑包
osgi導出包和非導出包
我想回顧一下OSGI包如何解決并使用Apache Karaf進行演示。 Karaf是基于Apache Felix內核的功能齊全的OSGI容器,并且是Apache ServiceMix集成容器的基石。 對于第一部分,我將討論OSGI框架如何解決捆綁包。 在第二部分中,我將使用Apache Karaf演示每個規則。 讓我們開始吧。捆綁包解決規則
OSGI 捆綁軟件的生命周期定義了捆綁軟件的可能狀態和過渡。 我們將討論捆綁包的“已解決”狀態,這意味著捆綁包在“安裝”之后以及滿足其所有必需的依賴關系時可以達到的狀態。 傳統的Java類加載易受運行時ClassCastException的影響,在這種情況下,來自兩個不同類加載器的兩個具有相同完全限定名稱的類會混合在一起,并且一個錯誤的類路徑空間中將使用一個類。 OSGI的主要目標之一是通過在部署時解決所有依賴關系來避免這種運行時異常,因為在部署時“快速”失敗的想法比嘗試在運行時跟蹤類加載問題更容易調試。 例如,考慮一下如何在Weblogic部署中調試一些未找到的類或類強制轉換異常。 OSGI解決了這個問題。 為了使分發包達到“已解決”狀態,必須滿足其依賴關系。 考慮這樣的“快速失敗”捆綁解決方案:如果您使用spring應用程序,并且由于缺少bean定義而無法正確連接其中一個bean,那么您將在部署時(而不是在有客戶時)知道這一點。調用您的代碼。 OSGI遵循相同的原則。 而不是對象級的接線依賴關系,我們是接線模塊和類加載的依賴關系。 一個簡單的解釋,即解決了其依賴關系的捆綁軟件可能是這樣的:如果捆綁軟件導入(導入包裝)特定的軟件包,則該軟件包必須由另一個捆綁軟件的導出(導出軟件包)提供。 如果捆綁軟件A具有Import-Package:org.apache.foo,則必須部署的捆綁軟件具有Export-Package:org.apache.foo對于每個Import-Package包聲明,必須有一個具有相同包的對應Export-Package
捆綁包還可以將其他屬性附加到它導入或導出的包中。 如果我們在示例中添加了version屬性,該怎么辦:
Bundle-Name: Bundle A
Import-Package: org.apache.foo;version="1.2.0"
Bundle-Name: Bundle B
Export-Package: org.apache.foo;version="1.2.0"
請注意,反之則不然......如果捆B出口版本1.2.0,則不需要捆綁到指定版本1.2.0。 它可以使用此導入并解決問題:
Bundle-Name: Bundle A
Import-Package: org.apache.foo
Import-Package準確規定了它需要的版本(或屬性),并且必須存在具有相同屬性的相應Export-Package
如果您遇到方案A導入軟件包并指定由兩個軟件包提供的版本的情況,會發生什么情況: Bundle-Name: Bundle A
Import-Package: org.apache.foo;version="1.2.0"
Bundle-Name: Bundle B
Export-Package: org.apache.foo;version="1.2.0"
Bundle-Name: Bundle C
Export-Package: org.apache.foo;version="1.2.0"
捆綁軟件A使用哪個捆綁軟件?
答案是,這取決于首先安裝了哪個捆綁包(B或C)。
當找到多個具有相同版本的軟件包時,首先安裝的軟件包用于滿足依賴性
在解決一些捆綁包之后,熱部署捆綁包會使事情變得更加復雜。 如果先安裝Bundle B,然后嘗試同時安裝Bundle A和以下Bundle D,該怎么辦: Bundle-Name: Bundle D
Export-Package: org.apache.foo;version="1.3.0"
從上面我們可以看到,捆綁軟件A(1.2.0)中的版本聲明表示最低版本為1.2.0; 因此,如果有更高版本可用,它將選擇該版本(本例中為Bundle D版本1.3.0)。 但是,這將我們帶到了束分解的另一個時間規則:
已解決的捆綁包比未解決的捆綁包具有更高的優先級
原因是OSGI框架傾向于支持給定捆綁軟件的可重用性。 如果已解決,并且新的捆綁軟件需要它,那么即使不需要,它也不會嘗試擁有同一軟件包的許多其他版本。
捆綁“使用”指令
上面關于束解析的規則仍然不夠,并且在運行時仍可能使用錯誤的類,從而導致類轉換異常或類似事件。 你看到什么可能會丟失嗎? 如果我們有這種情況怎么辦。 捆綁軟件A導出一個包org.apache.foo ,其中包含一個類FooClass。 FooClass具有一個返回BarClass類型的對象的方法,但是BarClass不在捆綁軟件的類空間中定義,它的導入方式如下: public class FooClass {public BarClass execute(){ ... } } Bundle-Name: Bundle A
Import-Package: org.apache.bar;version="3.6.0"
Export-Package: org.apache.foo;version="1.2.0"
到目前為止,只要有另一個捆綁包可以正確導出具有正確版本的org.apache.bar ,一切就可以了。
Bundle-Name: Bundle B
Export-Package: org.apache.bar;version="3.6.0"
這兩個捆綁包可以解決。 現在,如果我們再安裝兩個捆綁包,捆綁包C和捆綁包D如下所示:
Bundle-Name: Bundle C
Import-Package: org.apache.foo;version="1.2.0", org.apache.bar;version="4.0.0"
Bundle-Name: Bundle D
Export-Package: org.apache.bar;version="4.0.0"
Bundle-Name: Bundle A
Import-Package: org.apache.bar;version="3.6.0"
Export-Package: org.apache.foo;version="1.2.0"";uses:=org.apache.bar
使用Apache Karaf
OSGI容器Karaf基于Apache Felix核心,但是如果需要可以替換Equinox核心。 Karaf是功能齊全的OSGI容器,并且是Apache ServiceMix集成容器的基石。 ServiceMix基本上是Karaf,但專門針對Apache Camel,Apache ActiveMQ和Apache CXF進行了調整。 本教程將需要Maven和Karaf。 從maven網站下載maven 。 按照Karaf網站上的入門指南中的說明下載并安裝karaf。 您還將需要此示例附帶的代碼。 您可以在我的github倉庫中獲得它 。 獲得它之后,請確保從頂級項目運行“ mvn install”。 這將構建并將所有捆綁軟件安裝到本地 Maven存儲庫中。 盡管可以通過幾種不同的方式安裝捆綁軟件,但使用maven最為簡單。 請注意,此示例代碼主要由沒有任何實際Java類的程序包名稱組成(本教程指定的情況除外)。首先要做的是啟動karaf。 在普通發行版中,不應安裝捆綁軟件。 通過在karaf命令行中執行“ osgi:list”來驗證這一點。 按照順序,我們將測試上面給出的規則。
對于每個Import-Package包聲明,必須有一個具有相同包的對應Export-Package
為了測試此規則,讓我們從示例捆綁軟件中安裝捆綁軟件A。 捆綁包A指定“ org.apache.foo”包的導入包。 根據第一個規則,此捆綁包無法移至“已解決”狀態,因為沒有對應的捆綁包具有org.apache.foo的“導出包”。 在karaf命令行中,輸入“ osgi:install mvn:explore-bundle-resolution / bundleA / 1.0?”。 這將安裝bundleA捆綁軟件。 現在再次執行“ osgi:list”。 您應該看到捆綁軟件已安裝,并且在“狀態”列下應顯示為“已安裝”。 現在,嘗試“ osgi:resolve bundle id ”,其中bundle id是“ osgi:list”命令中列出的ID。 這將嘗試解決所有捆綁軟件依賴關系,并將其置于“已解決”狀態。 但是,它無法解決。 再次鍵入“ osgi:list”以查看捆綁軟件的狀態。 即使我們要求OSGI解決它,它仍然處于“已安裝”狀態。 讓我們找出原因。 執行“ osgi:headers 捆綁包ID ”。 在導入包下,您應該看到以紅色列出的包名稱org.apache.foo。 缺少此依賴項,因此讓我們添加它。 輸入“ osgi:install -s mvn:explore-bundle-resolution / bundleB / 1.0?”。 注意命令中的“ -s”開關。 這告訴OSGI一旦安裝了捆綁軟件就啟動它。 現在,再次鍵入osgi:resolve命令(帶有適當的捆綁軟件ID)。 現在,這將解決捆綁包。Import-Package準確規定了它需要的版本(或屬性),并且必須存在具有相同屬性的相應Export-Package
讓我們安裝捆綁軟件C:“ osgi:install -s mvn:explore-bundle-resolution / bundleC / 1.0? 再次列出捆綁軟件,您將看到盡管捆綁軟件C依賴于org.apache.foo,但它指定的Import-Package的特定版本為1.5。 沒有解決的版本1.5,因此捆綁軟件C也將無法解決。 捆綁包D恰巧導出了版本等于1.5的軟件包org.apache.foo。 使用-s啟動捆綁軟件D,就像安裝其他捆綁軟件一樣安裝它。 現在嘗試解析捆綁軟件C,它應該可以工作(“ osgi:resolve bundle id ”)。
當找到多個具有相同版本的軟件包時,首先安裝的軟件包用于滿足依賴性
該規則表示,如果有多個使用相同版本導出的軟件包,則OSGI將在嘗試解析導入軟件包的軟件包時選擇要使用的第一個安裝的軟件包。 繼續前面的示例,其中我們安裝了捆綁軟件C和D…請考慮捆綁軟件D導出org.apache.foo; version = 1.5。 因此,如果我們安裝輸出完全相同的軟件包和版本的軟件包F,則應該看到軟件包C是用軟件包D中的軟件包而不是軟件包F來解決的。讓我們看看..安裝軟件包F:“ osgi:install -s mvn: Explore-bundle-resolution / bundleF / 1.0?。 執行osgi:list并查看捆綁軟件D和F均已正確安裝并且為“活動”狀態。 這是OSGI的一項很酷的功能:我們可以同時部署同一軟件包的多個版本(在此示例中包括完全相同的版本)。 現在,我們應該卸載捆綁軟件C并重新安裝它,以查看它使用哪個捆綁軟件來解析其org.apache.foo的導入。 嘗試運行“ osgi:uninstall bundle id ”以卸載捆綁軟件C。現在,使用上面的命令重新安裝它。 它應該確定使用捆綁軟件D。使用“ package:import 捆綁軟件ID ”進行驗證。 您可以嘗試左右切換,以解決F問題。 您可能需要使用“ osgi:refresh”來刷新OSGI捆綁軟件。已解決的捆綁包比未解決的捆綁包具有更高的優先級
在某種程度上,我們已經在上一條規則中看到了這一點,但是該規則在熱部署時會起作用。 這留給讀者練習,因為這篇文章已經很長了,我接下來將介紹“ uses”指令。捆綁“使用”指令
“ uses”指令添加了最后的規則和約束之一,以避免運行時類廣播異常。 為了模擬“ uses”指令的工作方式,我們將安裝捆綁軟件G,H,I和J,并注意容器如何執行“ uses”指令。 捆綁軟件G代表一種“服務”模塊,客戶端模塊可以調用該服務模塊以“執行”某種形式的處理并返回結果。 它返回的結果是來自捆綁軟件H的BarClass類型的對象。但是,如果客戶端調用捆綁軟件G,它也必須使用捆綁軟件H的BarClass,否則將導致類強制轉換異常。 在我們的示例中,捆綁軟件I是客戶端代碼,捆綁軟件J代表BarClass的不同版本。 以您喜歡的任何順序安裝捆綁軟件,但我的演示遵循以下順序:J,H,G,I。請注意,即使捆綁軟件H是org.apache.bar的版本確實是來自捆綁軟件H的2.0.0版本。是第二次安裝的(與上面的規則相反)。 這是因為捆綁軟件G指定了“ uses”指令依賴于org.apache.bar的特定版本。參考:在Christian Posta Software博客上,從我們的JCG合作伙伴 Christian Posta 了解如何解決OSGI捆綁 軟件 。
翻譯自: https://www.javacodegeeks.com/2012/05/understanding-how-osgi-bundles-get.html
osgi導出包和非導出包
總結
以上是生活随笔為你收集整理的osgi导出包和非导出包_了解如何解决OSGI捆绑包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式的Java 8 Lambda表达
- 下一篇: 腾讯阿里入局,百亿卡牌会是门好生意吗?