JPMS 全稱是 Java Platform Module system(Java 平臺模塊化系統(tǒng))滔灶。它的目的簡單直接:編譯期間檢查和強(qiáng)化封裝肛宋。隨之而來的好處就是及時(shí)反饋咐容,不用等到運(yùn)行時(shí)才出現(xiàn)NoClassDefFoundError
授药;局部化影響幅疼,便于松耦合的開發(fā)和調(diào)優(yōu)晓勇,當(dāng)然還有運(yùn)行時(shí)的安全堂飞。
編譯期檢查
JPMS 要求每個(gè)定義好的模塊下面放置 module-info.java 描述文件(Module Descriptor),用于描述本模塊依賴(requires)外部哪些模塊绑咱,以及對外暴露(exports)本模塊中的哪些包(package)绰筛。
一旦描述了依賴外部的哪些模塊,編譯時(shí)描融,就會(huì)自動(dòng)檢查這些模塊是否已經(jīng)處于module path 下铝噩,如果不在就會(huì)報(bào)錯(cuò)。
強(qiáng)化封裝
除了原有的訪問修飾符 public, protected, private, default
形成的訪問限制外窿克,模塊又強(qiáng)化一層有訪問控制骏庸。除非模塊通過exports
關(guān)鍵字暴露出某些包,否則即便是public
的類年叮,外部也無法訪問具被。另外值得注意的是,以前即使是private
的方法谋右,使用反射調(diào)用setAccessible(true)
也可以隨意調(diào)用硬猫,但在 JPMS 下是行不通的。
項(xiàng)目實(shí)驗(yàn)
基于上述的基礎(chǔ)知識改执,我在原來托管在 github 上的開源項(xiàng)目 underscore.string.java 上另起了一個(gè) jigsaw 的分支 underscore.string.java-jigsaw啸蜜,實(shí)驗(yàn)了單個(gè)模塊的用法。
基本步驟
- src/main/java/ 目錄下新建 module-info.java
- 引入
gradle plugin org.gradle.java.experimental-jigsaw
- 修改 .travis.yml 以支持 java9 編譯
1. 模塊描述文件
module com.lambeta.underscorestring {
exports com.lambeta;
requires guava;
}
為了方便別人調(diào)用辈挂,需要起一個(gè)比較簡短的名字衬横,又因?yàn)樽詈梦ㄒ唬杂昧?com.lambeta.underscorestring
终蒂。這個(gè)模塊會(huì)導(dǎo)出包 com.lambeta
蜂林,事實(shí)上,我的項(xiàng)目只有一個(gè)包拇泣。另外噪叙,它需要依賴 guava
模塊。
2. gradle 插件
gradle 如何支持 java9 的模塊系統(tǒng)霉翔,這篇文章已經(jīng)細(xì)說睁蕾。我最終還是選用了一個(gè)實(shí)驗(yàn)版的插件使用,因?yàn)楸容^簡單。
plugins {
id 'org.gradle.java.experimental-jigsaw' version '0.1.1'
}
javaModule.name = 'com.lambeta.underscorestring'
javadoc {
excludes = ['module-info.java']
}
告知 gradle子眶,這個(gè)模塊的名字是 com.lambeta.underscorestring
瀑凝,這個(gè)和 gradle 的多模塊項(xiàng)目一起使用,效果最佳臭杰。
javadoc 的配置粤咪,主要針對是執(zhí)行 javadoc 任務(wù),出現(xiàn)了 module not found: guava
的錯(cuò)誤渴杆。這應(yīng)該是 gradle javadoc 的一個(gè) bug寥枝,Maven 項(xiàng)目中有類似的記載,后續(xù)會(huì)解決将塑。不過現(xiàn)在脉顿,直接跳過該文件蝌麸。
3. CI 服務(wù)
language: java
jdk: oraclejdk9
sudo: false
dist: trusty
script:
"./gradlew check -i"
addons:
hosts:
- lambetaBuild
hostname: lambetaBuild
光速跟進(jìn)的travis.ci 已經(jīng)支持了 oracle jdk9点寥,稍加配置,就可以使用上持續(xù)集成服務(wù)来吩。
當(dāng)然敢辩,這里面還有不少需要琢磨的內(nèi)容,比如:guava18 在 gradle4.2 下如何就能作為模塊 guava
被依賴弟疆?要知道戚长,guava23.1 還沒有加上 Automatic-Module-Name 呢。