翻譯自:
Why You Need Bnd 作者:Peter Kriens(OSGi聯盟主席)
為什么我們需要Bnd?
剛收到一個Google提醒,是關于一篇談論OSGi的博客文章。文章作者Jilles van Gurp開篇便稱贊OSGi,但隨之抨擊OSGi的一些工具。他不能忍受的關鍵,在于需要把包的導入一行一行的加到manifest,他還認為manifest的格式很糟糕。
我不同意他的看法,因為Bnd完全可以滿足他提到的需求。
“
管理bundle之間的依賴比簡單的import要難得多。以前我想要用某個庫,我就下載下來放在classpath里,在代碼里敲一些首字母,用ctrl+space就可以知道他里面的API。但在OSGi里就比較麻煩了,你把bundle下載下來(假如網上有的話),還要判斷它里面暴露了哪些包,然后才能決定究竟使用哪些包。”
我贊同Eclipse JDT是比PDE功能更加強大,更加好用。但如果用bnd工具,你就可以像你剛才描述的那樣工作。你可以像以前一樣使用庫,你甚至不需要使用PDE,比如我就只用Eclipse JDT來完成工作。Bnd會讀取配置文件里的描述來決定classpath的哪些內容會被打到bundle里。通配符和默認值使得這個描述盡可能的短。然后Bnd會計算需要導入的包和其它一些相關信息。
“
大部分庫不是以bundle的形式發布的。bundle是一個新的概念,他不能向后兼容以前的jar包(而這是很多第三方提供庫的主要形式)。我認為這是一個沒必要的限制,他們更應該默認的把jar看成導出所有包而且引用所有依賴包的bundle。從jar里取到這些信息應該是不難的,至少應該提供一個工具給我們做轉換之用吧”
跟上面說的一樣,通過使用Bnd,你的這些要求也可以得到滿足。Bnd有一個封裝功能就是做這個轉換。但實際上很多jar文件的依賴關系都很糟糕,所以這個轉換也不是那么輕松。我們經常需要加入可選的導入或者忽略導入來使得bundle能夠被安裝到系統中。當你分析一個JAR文件時(Bnd就可以完成這個功能),你經常會發現里面有大量沒用到(或很少用到)的依賴。
“
最后,我很討厭要寫這樣一個格式糟糕的屬性文件(manifest),我發現需要在manifest后加上一個空行的bug仍然存在(如果少了這個會出莫名其妙的錯誤)。這個就像makefile里必須用tab而不能用空格一樣令人煩惱”
嗯,這個確實有點煩,但是通過使用Bnd,你也不用再擔心這些小事。一個bnd文件就是一個屬性文件,而且不管你文件中的一行需要多長,它都能夠處 理。行可以通過“”來延續到下一行,誰會在乎多出的最后一個空行呢?你還可以在文件中添加注釋。Bnd讀取這些屬性,通過Java內嵌的 Manifest類生成一個規范的manifest。在讀取過程中Bnd會檢查屬性頭是否正確。我們隨便看一個Bnd的例子,它可能像這樣:
Export-Package: aQute.service.*
Import-Package: javax.servlet.http;version="[2,3)", *
然而,Jilles的抱怨還沒結束,他又對OSGi有意見了:
“
當然我們有一個更好的方式來做這個,就是使用Java5.0里剛引入的annotations。可以理解OSGi需要兼容老的版本(使得拙劣的設計也有臺階下),但很明顯我們應該更注重對新版本的應用,拋棄陳舊的方式。實際上,對于導入和導出包來說,我更希望能把粒度細化到類和方法的層面上”
Annotations現在比較流行了,他們在自己的領域發揮的很好。但這應該是一個分離關注點的問題。我想我們都知道要分離業務邏輯和底層架構。在類或方法里加入annotations來定義約束顯然會搞亂你的代碼。我也認為讓用戶自己管理依賴挺復雜。我們需要更好的工具支持,讓用戶手動管理代碼里的依賴很容易錯誤百出。所以我不確定annotations能解決問題。通過在代碼里定義版本號(編輯manifest或包目錄下的 packageinfo文件),Bnd可以找出引用的包版本。這種方式簡單一致,盡管它不能處理版本范圍。我大概知道要怎么做可以處理版本范圍(在 classpath里允許同一個包有多個版本,然后比較版本之間的差異),但是,這需要時間。。。
“
還有一個問題,在java中包沒有它們自己單獨的表達方式。它們只是在類的包聲明里被提到,但沒有自己的獨立表述。這意味著很難針對包添加annotation(不過你可以通過package-info.java來達到這個效果)。”
仍舊像剛才說的那樣,我不確定annotations是不是最佳方案,因為它會把業務邏輯的代碼搞得很亂。在OSGi中,你可以通過manifest(或者Bnd)來定義包的屬性。
此外,Bnd還有很多其它特點,比如說下面這些:
* Bnd還被用在Maven構建工具的Felix Maven-bundle插件中。
* Bnd還是一個Eclipse插件,它在.bnd和.jar文件的右鍵菜單中添加了執行項。
* 可以集成來自任何地方的資源,無論是通過文件系統還是URL。不需要首先為這些資源找一個文件夾來放置,因為JAR文件的構建是實時進行的。
* 資源名稱中可以包含變量,這些變量在構建時會被自動替換成實際值。
* 通過在classpath中定義包引用,可以很容易地把這些包集成到jar中。如果你只是想依賴另一個bundle的某一部分,而不想產生額外的依賴,這樣做是很方便的。
* Bnd也可以在導出時生成uses語句。uses語句用來表述當前包要用到的所有包。框架將會用這些信息來創建一致的類空間。
* 可以內聯其他Jar文件或目錄。
* 還有很多很多。。。
我不是說Bnd已經完美了。我希望能多花點時間來擴展它,讓它看著就像這樣:一個管理依賴的圖形編輯器,有著更好的語法支持,與Eclipse構建器集成得更好,等等。
Peter Kriens
(譯完)
版權所有 羅明