本文是純第三方依賴的Eclipse插件的構(gòu)建和自動(dòng)更新的后續(xù)钥顽。
背景
之前構(gòu)建純第三方依賴的Eclipse插件的時(shí)候蔚袍,通過(guò)Export-Package
導(dǎo)出了不少包(例如apache commons、xstream、slf4j等)給其他插件使用窃诉,因?yàn)閷?dǎo)出包太多,導(dǎo)致Eclipse插件在查找類的時(shí)候出現(xiàn)了性能問(wèn)題赤套,所以現(xiàn)在想僅開放必要的內(nèi)部包飘痛,公共組件的包由外部插件提供,一些必要的調(diào)用通過(guò)該插件內(nèi)部的代碼類來(lái)提供容握。所以做了兩個(gè)修改:
- 從
Export-Package
中移除了公共組件的包宣脉,僅保留項(xiàng)目相關(guān)jar的包的導(dǎo)出。 - 代碼工程中增加了src/main/java源碼文件夾剔氏,通過(guò)自定義工具類實(shí)現(xiàn)對(duì)插件內(nèi)部類的配置塑猖。
經(jīng)過(guò)修改后重新打包竹祷,發(fā)現(xiàn)打包后的bundle jar中除了自定義的類、第三方j(luò)ar之外羊苟,Export-Package
中定義的導(dǎo)出包及其中的類也被解壓到了bundle jar中塑陵,解壓后的包和class以及jar都存在于bundle jar中,這樣肯定是有問(wèn)題的践险。
問(wèn)題原因
通過(guò)查閱BND的資料猿妈,發(fā)現(xiàn)之前對(duì)Export-Package
的理解有誤,之前一直以為該配置對(duì)應(yīng)的是Bundle MANIFEST.MF中的Export-Package巍虫,添加到該配置中的插件包及插件內(nèi)部jar中的包可以供外部插件訪問(wèn)彭则。其實(shí)BND中的Export-Package
并不僅僅是這個(gè)功能,先貼一段BND中的解釋說(shuō)明:
<Export-Package>
The <Export-Package> instruction is a list of packages for the bundle to export. These packages are copied into the resulting bundle JAR file from the available classes (i.e., project classes, dependencies, and class path); thus, it is possible to include classes into your bundle that are not associated with source files in your project. <Export-Package> can be specified with package patterns using the '*' wildcard. Also, it is possible to exclude packages using negation by starting the package pattern with '!'. Thus, non-negated patterns indicate which of the available packages to include in the bundle, whereas negated patterns indicate which should not be included in the bundle.The list of package patterns is ordered and earlier patterns are applied before later patterns. For example, if you specify "org.foo.,!org.foo.impl" the second pattern has no effect since all org.foo packages have already been selected by the first pattern. Instead, you should specify "!org.foo.impl,org.foo.", which will export all org.foo packages except org.foo.impl.
Following standard OSGi R4 syntax, package patterns can include both directives and attributes, which will be copied appropriately into the generated Export-Package manifest header. Besides explicitly listing package version attributes, BND will also determine package versions by examining the source JAR file or from packageinfo files in the package directory.
注意上述說(shuō)明中的黑體部分占遥。重點(diǎn)在第一段俯抖,第一段已經(jīng)說(shuō)明了添加到Export-Package中的包中的class會(huì)被復(fù)制到生成的bundle jar中,同時(shí)加入到MANIFEST.MF的Export-Package頭中瓦胎。
但是我們之前構(gòu)建的bundle jar芬萍,并沒(méi)有將Export-Package包中的class復(fù)制到bundle jar中,是本次增加了src/main/java后才出現(xiàn)解壓class的現(xiàn)象搔啊,原因未知柬祠。
解決辦法
BND官網(wǎng)的常見問(wèn)題文檔中,第一條即是該問(wèn)題“當(dāng)我嵌入bundle中一個(gè)依賴時(shí)為什么我在bundle jar中看見了重復(fù)的類负芋?”漫蛔,看來(lái)這個(gè)問(wèn)題比較普遍_。先來(lái)看BND給的解釋說(shuō)明:
Having two copies of classes, both unpacked and embedded as jars, is a sign that your Embed-Dependency and Export-Package instructions are overlapping. Export-Package tells BND to pull in classes found in the named packages from the build classpath and add them to the bundle, Embed-Dependency tells BND to embed (or inline if enabled) whole artifacts in the bundle.
BND的意思是如果你在最終的bundle jar中看見了重復(fù)的class和它所在的jar旧蛾,說(shuō)明你在Embed-Dependency
和Export-Package
中的定義重疊了莽龟。換句話說(shuō)就是,你同時(shí)配置了Embed-Dependency
和Export-Package
锨天,Export-Package將包中的class解壓到bundle jar毯盈,Embed-Dependency將jar復(fù)制到bundle jar中。
如果你僅僅是想在最終的bundle jar的MANIFEST.MF的Export-Package頭中導(dǎo)出包病袄,并不想同時(shí)將包中的class解壓到bundle中搂赋,你需要使用<_exportcontents>替代Export-Package,具體做法:
- 移除<Export-Package>
- 在Embed-Dependency之后添加<_exportcontents>益缠,例如:
<Embed-Dependency>*</Embed-Dependency>
<_exportcontents>org.apache.commons.*</_exportcontents>
參考資料
Apache Felix Bundle Plugin Frequently Asked Questions
使用BND構(gòu)建包含純第三方依賴的Eclipse插件