在本系列的上篇文章中,我們講到了如何自定義Property,在本篇文章中,我們將講到如何使用java Plugin。
請通過以下方式下載本系列文章的Github示例代碼:
git clone https://github.com/davenkin/gradle-learning.git
Gradle最常用的Plugin便是java Plugin了。和其他Plugin一樣,java Plugin並沒有什么特別的地方,只是向Project中引入了多個Task和Property。當然,java Plugin也有比較與眾不同的地方,其中之一便是它在項目中引入了構建生命周期的概念,就像Maven一樣。但是,和Maven不同的是,Gradle的項目構建生命周期並不是Gradle的內建機制,而是由Plugin自己引入的。
(一)java Plugin引入的主要Task
執行“gradle build”,我們已經可以看到java Plugin所引入的主要Task:
:compileJava :processResources :classes :jar :assemble :compileTestJava :processTestResources :testClasses :test :check :build BUILD SUCCESSFUL Total time: 4.813 secs
build也是java Plugin所引入的一個Task,它依賴於其他Task,其他Task又依賴於另外的Task,所以有了以上Task執行列表。以上Task執行列表基本上描述了java Plugin向項目中所引入的構建生命周期概念。
除了定義眾多的Task外,java Plugin還向Project中加入了一些額外的Property。比如,sourceCompatibility用於指定在編譯Java源文件時所使用的Java版本,archivesBaseName用於指定打包成Jar文件時的文件名稱。
(二)Java項目的目錄結構
在默認情況下,Gradle采用了與Maven相同的Java項目目錄結構:
關於Maven標准目錄結構,請參考Maven官網。當然,跟Maven一樣,以上只是默認的目錄結構,我們可以通過配置來修改這些目錄結構。
(三)配置已有source set
Gradle在采用了Maven目錄結構的同時,還融入了自己的一些概念,即source set。對於上圖中的目錄結構,Gradle實際上為我們創建了2個source set,一個名為main,一個名為test。
請注意,這里的source set的名字main與上圖目錄結構中的main文件夾並無必然的聯系,只是在默認情況下,Gradle為了source set概念到文件系統目錄結構的映射方便,才采用了相同的名字。對於test, 也是如此。我們完全可以在build.gradle文件中重新配置這些source set所對應的目錄結構,同時,我們還可以創建新的source set。
從本質上講,Gradle的每個source set都包含有一個名字,並且包含有一個名為java的Property和一個名為resources的Property,他們分別用於表示該source set所包含的Java源文件集合和資源文件集合。在實際應用時,我們可以將他們設置成任何目錄值。比如,我們可以重新設置main的目錄結構:
sourceSets { main { java { srcDir 'java-sources' } resources { srcDir 'resources' } } }
此時所對應的項目目錄結構如下:
我們重新設置了main的目錄結構,而對於test,我們保留了Gradle默認的目錄結構。
(四)創建新的source set
要創建一個新的source set也是非常簡單的,比如,我們可以創建一個名為api的source set來存放程序中的接口類:
sourceSets {
api
}
當然,以上配置也可以與main放在一起。在默認情況下,該api所對應的Java源文件目錄被Gradle設置為${path-to-project}/src/api/java,而資源文件目錄則被設置成了${path-to-project}/src/api/resources。我們也可以像上面的main一樣重新對api的目錄結構進行配置。
Gradle會自動地為每一個新創建的source set創建相應的Task,創建規律為:對於名為mySourceSet的source set,Gradle將為其創建compile<mySourceSet>Java、process<mySourceSet>Resources和<mySourceSet>Classes這3個Task。對於這里api而言,Gradle會為其創建名為compileApiJava、processApiResource和apiClasses Task。我們可以在命令行中執行"gradle apiClasses"。
你可能會注意到,對於main而言,Gradle並沒有相應的compileMainJava,原因在於:由於main是Gradle默認創建的source set,並且又是及其重要的source set,Gradle便省略掉了其中的“Main”,而是直接使用了compileJava作為main的編譯Task。對於test來說,Gradle依然采用了compileTestJava。
通常的情況是,我們自己創建的名為api的source set會被其他source set所依賴,比如main中的類需要實現api中的某個接口等。此時我們需要做兩件事情。第一,我們需要在編譯main之前對api進行編譯,即編譯main中Java源文件的Task應該依賴於api中的Task:
classes.dependsOn apiClasses
第二,在編譯main時,我們需要將api編譯生成的class文件放在main的classpath下。此時,我們可以對main和test做以下配置:
sourceSets { main { compileClasspath = compileClasspath + files(api.output.classesDir) } test { runtimeClasspath = runtimeClasspath + files(api.output.classesDir) } }
之所以需要對test的runtimeClasspath進行設置,是因為在運行測試時我們也需要加載api中的類。
在下一篇文章中,我們將講到如何管理依賴。