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