Java 外掛為專案新增 Java 編譯以及測試和組合功能。它是許多其他 JVM 語言 Gradle 外掛的基礎。您可以在 建置 Java 專案 章節中找到 Java 外掛的綜合介紹和概觀。
如上所述,此外掛新增了處理 JVM 專案的基本建置區塊。其功能集已被其他外掛取代,根據您的專案類型提供更多功能。您不應將其直接套用至您的專案,而應查看 |
使用方式
若要使用 Java 外掛,請在您的建置指令碼中包含下列內容
plugins {
java
}
plugins {
id 'java'
}
工作
Java 外掛會為您的專案新增許多工作,如下所示。
compileJava
— JavaCompile-
依賴於:所有有助於編譯類別路徑的任務,包括來自專案的
jar
任務,這些專案透過專案相依性位於類別路徑上使用 JDK 編譯器編譯生產 Java 原始檔。
processResources
— ProcessResources-
將生產資源複製到生產資源目錄中。
classes
-
依賴於:
compileJava
、processResources
這是一個綜合任務,僅依賴於其他任務。其他外掛程式可能會附加其他編譯任務到此任務。
compileTestJava
— JavaCompile-
依賴於:
classes
,以及有助於測試編譯類別路徑的所有任務使用 JDK 編譯器編譯測試 Java 原始檔。
processTestResources
— Copy-
將測試資源複製到測試資源目錄中。
testClasses
-
依賴於:
compileTestJava
、processTestResources
這是一個綜合任務,僅依賴於其他任務。其他外掛程式可能會附加其他測試編譯任務到此任務。
jar
— Jar-
依賴於:
classes
根據附加到
main
原始檔集的類別和資源,組建生產 JAR 檔。 javadoc
— Javadoc-
依賴於:
classes
使用 Javadoc 為生產 Java 原始檔產生 API 文件。
test
— Test-
依賴於:
testClasses
,以及產生測試執行階段類別路徑的所有任務使用 JUnit 或 TestNG 執行單元測試。
clean
— Delete-
刪除專案建置目錄。
cleanTaskName
— Delete-
刪除由指定任務產生的檔案。例如,
cleanJar
會刪除由jar
任務產生的 JAR 檔,而cleanTest
會刪除由test
任務產生的測試結果。
SourceSet 任務
對於您新增到專案的每個原始檔集,Java 外掛程式會新增下列任務
compileSourceSetJava
— JavaCompile-
依賴於:所有貢獻於來源設定編譯類別路徑的任務
使用 JDK 編譯器編譯給定來源設定的 Java 來源檔案。
processSourceSetResources
— 複製-
將給定來源設定的資源複製到資源目錄中。
sourceSetClasses
— 任務-
依賴於:
compileSourceSetJava
、processSourceSetResources
準備給定來源設定的類別和資源以進行封裝和執行。某些外掛程式可能會為來源設定新增其他編譯任務。
生命週期任務
Java 外掛程式會將某些任務附加到 基本外掛程式 定義的生命週期任務(Java 外掛程式會自動套用)上,同時也會新增幾個其他生命週期任務
組建
-
依賴於:
jar
彙總專案中所有檔案的彙總任務。此任務由基本外掛程式新增。
檢查
-
依賴於:
測試
執行驗證任務(例如執行測試)的彙總任務。某些外掛程式會將自己的驗證任務新增到
檢查
。如果您希望自訂測試
任務在完整建置中執行,也應該將它們附加到此生命週期任務。此任務由基本外掛程式新增。 建置
-
依賴於:
檢查
、組建
執行專案完整建置的彙總任務。此任務由基本外掛程式新增。
buildNeeded
-
依賴於:
建置
,以及testRuntimeClasspath
組態中所有專案的buildNeeded
任務。執行專案及其所有依賴專案的完整建置。
buildDependents
-
依賴於:
建置
,以及所有專案的buildDependents
任務,這些專案在testRuntimeClasspath
組態中將此專案設為依賴項執行專案及其所有依賴專案的完整建置。
buildConfigName
— 任務規則-
依賴於:所有產生附加到命名(ConfigName)組態的成品的任務
彙總指定組態的成品。此規則由基本外掛程式新增。
下圖顯示這些任務之間的關係。

專案配置
Java 外掛程式假設專案配置如下所示。這些目錄不需要存在或包含任何內容。Java 外掛程式會編譯它找到的任何內容,並處理任何遺失的內容。
src/main/java
-
生產用 Java 原始碼。
src/main/resources
-
生產用資源,例如 XML 和屬性檔案。
src/test/java
-
測試用 Java 原始碼。
src/test/resources
-
測試用資源。
src/sourceSet/java
-
名為 sourceSet 的原始碼集的 Java 原始碼。
src/sourceSet/resources
-
名為 sourceSet 的原始碼集的資源。
變更專案配置
您可以透過設定適當的原始碼集來設定專案配置。以下各節將更詳細地說明。以下是一個簡短範例,其中變更了主 Java 和資源原始碼目錄。
sourceSets {
main {
java {
setSrcDirs(listOf("src/java"))
}
resources {
setSrcDirs(listOf("src/resources"))
}
}
}
sourceSets {
main {
java {
srcDirs = ['src/java']
}
resources {
srcDirs = ['src/resources']
}
}
}
原始碼集
外掛程式會新增下列 原始碼集
main
-
包含專案的生產用原始碼,編譯後組裝成 JAR 檔。
test
-
包含您的測試用原始碼,使用 JUnit 或 TestNG 編譯並執行。這些通常是單元測試,但只要所有測試共用相同的編譯和執行時期類別路徑,您就可以將任何測試包含在此原始碼集中。
原始碼集屬性
下表列出原始碼集的一些重要屬性。您可以在 SourceSet 的 API 文件中找到更多詳細資訊。
name
— (唯讀)String
-
原始碼集的名稱,用於識別它。
output
— (唯讀) SourceSetOutput-
原始碼集的輸出檔案,包含其編譯的類別和資源。
output.classesDirs
— (唯讀) FileCollection-
預設值:
layout.buildDirectory.dir("classes/java/$name")
,例如 build/classes/java/main產生此來源組類別的目錄。可能包含其他 JVM 語言的目錄,例如 build/classes/kotlin/main。
output.resourcesDir
—File
-
預設值:
layout.buildDirectory.dir("resources/$name")
,例如 build/resources/main產生此來源組資源的目錄。
compileClasspath
— FileCollection-
預設值:
${name}CompileClasspath
組態編譯此來源組的來源檔案時要使用的類別路徑。
annotationProcessorPath
— FileCollection-
預設值:
${name}AnnotationProcessor
組態編譯此來源組的來源檔案時要使用的處理器路徑。
runtimeClasspath
— FileCollection-
預設值:
$output
、${name}RuntimeClasspath
組態執行此來源組的類別時要使用的類別路徑。
java
— (唯讀)SourceDirectorySet-
此來源組的 Java 來源檔案。僅包含在 Java 來源目錄中找到的
.java
檔案,並排除所有其他檔案。 java.srcDirs
—Set<File>
-
預設值:
src/$name/java
,例如 src/main/java包含此來源組的 Java 來源檔案的來源目錄。您可以將其設定為 此區段 中所述的任何值。
java.destinationDirectory
—DirectoryProperty
-
預設值:
layout.buildDirectory.dir("classes/java/$name")
,例如 build/classes/java/main產生已編譯 Java 來源的目錄。您可以將其設定為 此區段 中所述的任何值。
resources
— (唯讀)SourceDirectorySet-
此來源組的資源。僅包含資源,並排除資源目錄中找到的任何
.java
檔案。其他外掛程式,例如 Groovy 外掛程式,會從此集合中排除其他類型的檔案。 resources.srcDirs
—Set<File>
-
預設值:
[src/$name/resources]
包含此來源組資源的目錄。您可以將其設定為 此區段 中所述的任何類型的值。
allJava
— (唯讀) SourceDirectorySet-
預設值:與
java
屬性相同此來源組的所有 Java 檔案。某些外掛程式,例如 Groovy 外掛程式,會將其他 Java 來源檔案新增到此集合。
allSource
— (唯讀) SourceDirectorySet-
預設值:
resources
和java
屬性中所有內容的總和此來源組中所有語言的所有來源檔案。這包括所有資源檔案和所有 Java 來源檔案。某些外掛程式,例如 Groovy 外掛程式,會將其他來源檔案新增到此集合。
其他一些簡單的來源組範例
新增包含來源組類別的 JAR
tasks.register<Jar>("intTestJar") {
from(sourceSets["intTest"].output)
}
tasks.register('intTestJar', Jar) {
from sourceSets.intTest.output
}
為來源組產生 Javadoc
tasks.register<Javadoc>("intTestJavadoc") {
source(sourceSets["intTest"].allJava)
classpath = sourceSets["intTest"].compileClasspath
}
tasks.register('intTestJavadoc', Javadoc) {
source sourceSets.intTest.allJava
classpath = sourceSets.intTest.compileClasspath
}
新增測試套件來執行來源組中的測試
tasks.register<Test>("intTest") {
testClassesDirs = sourceSets["intTest"].output.classesDirs
classpath = sourceSets["intTest"].runtimeClasspath
}
tasks.register('intTest', Test) {
testClassesDirs = sourceSets.intTest.output.classesDirs
classpath = sourceSets.intTest.runtimeClasspath
}
相依性管理
Java 外掛程式會在您的專案中新增許多 相依性設定,如下所示。然後,compileJava
和 test
等任務會使用一個或多個設定來取得對應的檔案並使用它們,例如將它們置於編譯或執行時期類別路徑上。
相依性設定
如需 default
和 archives
設定的資訊,請參閱 基本外掛程式 參考文件。
如需 api
或 compileOnlyApi
設定的資訊,請參閱 Java 函式庫外掛程式 參考文件和 Java 專案的相依性管理。
implementation
-
僅實作相依性。
compileOnly
-
僅編譯時間相依性,在執行時期不使用。
compileClasspath
延伸compileOnly, implementation
-
編譯類別路徑,在編譯來源時使用。由
compileJava
任務使用。 annotationProcessor
-
編譯期間使用的註解處理器。
runtimeOnly
-
僅限執行時期的依賴項。
runtimeClasspath
延伸runtimeOnly, implementation
-
執行時期類別路徑包含實作的元素,以及僅限執行時期的元素。
testImplementation
延伸implementation
-
僅限測試的實作依賴項。
testCompileOnly
-
僅限編譯測試的額外依賴項,不會在執行時期使用。
testCompileClasspath
延伸testCompileOnly, testImplementation
-
測試編譯類別路徑,用於編譯測試來源時。由工作
compileTestJava
使用。 testRuntimeOnly
延伸runtimeOnly
-
僅限執行時期的依賴項,用於執行測試。
testRuntimeClasspath
延伸testRuntimeOnly, testImplementation
-
執行測試的執行時期類別路徑。由工作
test
使用。
下列圖表分別顯示 主要 和 測試 來源組的依賴項設定。您可以使用此圖例來詮釋顏色
-
綠色背景 — 您可以針對設定宣告依賴項。
-
藍灰色背景 — 此設定供工作使用,您不能用來宣告依賴項。
-
淺藍色背景,搭配等寬字體 — 工作。


對於您新增到專案的每個來源組,Java 外掛程式會新增下列依賴項設定
SourceSet 依賴項設定
sourceSetImplementation
-
給定來源組的編譯時間依賴項。由
sourceSetCompileClasspath, sourceSetRuntimeClasspath
使用。 sourceSetCompileOnly
-
給定來源組的僅限編譯時間依賴項,不會在執行時期使用。
sourceSetCompileClasspath
延伸sourceSetCompileOnly, sourceSetImplementation
-
編譯類別路徑,用於編譯來源時。由
compileSourceSetJava
使用。 sourceSetAnnotationProcessor
-
此來源組編譯期間使用的註解處理器。
sourceSetRuntimeOnly
-
給定來源組的僅限執行時期依賴項。
sourceSetRuntimeClasspath
延伸sourceSetRuntimeOnly, sourceSetImplementation
-
執行時期類別路徑包含實作的元素,以及僅限執行時期的元素。
貢獻的擴充
Java 外掛程式會將 java
延伸模組 新增至專案。這允許在專用 DSL 區塊內設定多個與 Java 相關的屬性。
java
延伸模組來設定工具鏈java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
以下是 java
延伸模組內可用的屬性和 DSL 函數清單,並附有簡短說明。
工具鏈和相容性
toolchain
-
Java 工具鏈,供使用 JVM 工具(例如編譯和執行)的任務使用。預設值:建置 JVM 工具鏈。
JavaVersion sourceCompatibility
-
編譯 Java 原始碼時要使用的 Java 版本相容性。預設值:此延伸模組中工具鏈的語言版本。
請注意,在多數情況下,使用 工具鏈 優於使用相容性設定。 JavaVersion targetCompatibility
-
要為其產生類別的 Java 版本。預設值:
sourceCompatibility
。
請注意,在多數情況下,使用 工具鏈 優於使用相容性設定。
封裝
withJavadocJar()
-
自動封裝 Javadoc,並使用成品
-javadoc.jar
建立變異javadocElements
,此成品將成為出版品的一部分。 withSourcesJar()
-
自動封裝原始碼,並使用成品
-sources.jar
建立變異sourceElements
,此成品將成為出版品的一部分。
目錄屬性
String reporting.baseDir
-
相對於建置目錄,要產生報表的目錄名稱。預設值:
reports
(唯讀) File reportsDir
-
要產生報表的目錄。預設值:
reporting.baseDirectory
String testResultsDirName
-
相對於建置目錄,要產生測試結果 .xml 檔案的目錄名稱。預設值:
test-results
(唯讀) File testResultsDir
-
要產生測試結果 .xml 檔案的目錄。預設值:
layout.buildDirectory.dir(testResultsDirName)
String testReportDirName
-
相對於報表目錄,要產生測試報表的目錄名稱。預設值:
tests
(唯讀) File testReportDir
-
要產生測試報表的目錄。預設值:
reportsDir/testReportDirName
String libsDirName
-
相對於建置目錄,要產生函式庫的目錄名稱。預設值:
libs
(唯讀) File libsDir
-
產生函式庫的目錄。預設值:
layout.buildDirectory.dir(libsDirName)
字串 distsDirName
-
產生發行版的目錄名稱,相對於建置目錄。預設值:
distributions
(唯讀) 檔案 distsDir
-
產生發行版的目錄。預設值:
layout.buildDirectory.dir(distsDirName)
字串 docsDirName
-
產生文件檔的目錄名稱,相對於建置目錄。預設值:
docs
(唯讀) 檔案 docsDir
-
產生文件檔的目錄。預設值:
layout.buildDirectory.dir(docsDirName)
字串 dependencyCacheDirName
-
快取來源依賴資訊的目錄名稱,相對於建置目錄。預設值:
dependency-cache
。
其他屬性
(唯讀) SourceSetContainer sourceSets
-
包含專案的來源組。預設值:非 Null SourceSetContainer
字串 archivesBaseName
-
用於檔案的基礎名稱,例如 JAR 或 ZIP 檔案。預設值:
projectName
Manifest manifest
-
包含在所有 JAR 檔案中的明細。預設值:空的明細。
慣例屬性 (已棄用)
Java 外掛程式會新增許多慣例屬性至專案。您可以在建置指令碼中使用這些屬性,就像它們是專案物件的屬性一樣。這些屬性已棄用,並由上述擴充套件取代。有關這些屬性的資訊,請參閱 JavaPluginConvention DSL 文件。
測試
有關更多詳細資訊,請參閱 Java 和 JVM 專案中的測試 章節。
發布
components.java
-
用於發布
jar
任務所建立的生產 JAR 的 SoftwareComponent。此組件包含 JAR 的執行時期依賴資訊。
另請參閱 java
擴充套件。
增量式 Java 編譯
Gradle 附帶一個精密的增量式 Java 編譯器,預設為啟用狀態。
這會為您帶來以下好處
-
增量式建置速度快很多。
-
變更的類別檔案數量會是最少的。不需要重新編譯的類別會保留在輸出目錄中不變。一個真正有用的範例情境是使用 JRebel,變更的輸出類別愈少,JVM 就愈能快速使用更新的類別。
為了幫助您了解增量式編譯運作的方式,以下提供一個高階概觀
-
Gradle 會重新編譯所有受變更影響的類別。
-
如果一個類別已變更,或它依賴於另一個受影響的類別,則它會受影響。這不論另一個類別是在同一個專案、另一個專案,甚至是外部函式庫中定義的都沒有關係。
-
一個類別的依賴關係會透過編譯器外掛程式,從其位元組碼或符號分析中的類型參照來決定。
-
由於來源保留註解在位元組碼中不可見,因此變更來源保留註解會導致完全重新編譯。
-
您可以透過應用良好的軟體設計原則(例如鬆散耦合)來改善增量式編譯效能。例如,如果您在具體類別和其依賴項之間放置介面,則依賴類別只會在介面變更時重新編譯,而不是在實作變更時重新編譯。
-
類別分析會快取在專案目錄中,因此在乾淨結帳後的第一個建置可能會比較慢。考慮在您的建置伺服器上關閉增量式編譯器。
-
類別分析也是儲存在建置快取中的輸出,這表示如果從建置快取中擷取編譯輸出,則增量式編譯分析也會被擷取,而且下一次編譯會是增量式的。
增量註解處理
從 Gradle 4.7 開始,增量編譯器也支援增量註解處理。所有註解處理器都需要選擇加入此功能,否則它們將觸發完整的重新編譯。
作為使用者,您可以在 --info
日誌中看到哪些註解處理器觸發了完整的重新編譯。如果在編譯任務中設定了自訂的 executable
或 javaHome
,增量註解處理將會停用。
讓註解處理器成為增量的
請先查看 增量 Java 編譯,因為增量註解處理建立在其上。
Gradle 支援兩種常見類別的註解處理器的增量編譯:「隔離」和「聚合」。請參閱以下資訊,以決定哪個類別適合您的處理器。
然後,您可以使用處理器 META-INF 目錄中的檔案,為增量編譯註冊您的處理器。格式為每行一個處理器,其中處理器類別的完整限定名稱及其不區分大小寫的類別以逗號分隔。
範例:註冊增量註解處理器
org.gradle.EntityProcessor,isolating org.gradle.ServiceRegistryProcessor,dynamic
如果您的處理器只能在執行階段決定它是否為增量的,您可以在 META-INF 描述符中將其宣告為「動態」,並在執行階段使用 Processor#getSupportedOptions() 方法傳回其真實類型。
範例:動態註冊增量註解處理器
@Override
public Set<String> getSupportedOptions() {
return Collections.singleton("org.gradle.annotation.processing.aggregating");
}
這兩個類別都有以下限制
-
它們只能讀取
CLASS
或RUNTIME
保留註解。 -
它們只能在使用者傳遞
-parameters
編譯器引數時讀取參數名稱。 -
它們必須使用 Filer API 產生它們的檔案。以任何其他方式寫入檔案將導致後續的靜默失敗,因為這些檔案不會被正確清理。如果您的處理器執行此操作,它就不能是增量的。
-
它們不能依賴於特定於編譯器的 API,例如
com.sun.source.util.Trees
。Gradle 會包裝處理 API,因此嘗試轉換為特定於編譯器的類型將會失敗。如果您的處理器執行此操作,它就不能是增量的,除非您有某些後備機制。 -
如果他們使用 Filer#createResource,
location
參數必須是 StandardLocation 中的下列值之一:CLASS_OUTPUT
、SOURCE_OUTPUT
或NATIVE_HEADER_OUTPUT
。任何其他參數都會停用增量處理。
「孤立」註解處理器
最快的類別,這些類別會孤立地查看每個註解元素,為其建立產生的檔案或驗證訊息。例如,EntityProcessor
可以為每個註解有 @Entity
的類型建立一個 <TypeName>Repository
。
範例:一個孤立的註解處理器
Set<? extends Element> entities = roundEnv.getElementsAnnotatedWith(entityAnnotation);
for (Element entity : entities) {
createRepository((TypeElement) entity);
}
「孤立」處理器有下列額外的限制
-
他們必須根據可從其 AST 存取的資訊,為註解類型做出所有決定(產生程式碼、驗證訊息)。這表示您可以分析類型的超類別、方法傳回類型、註解等,甚至可以遞迴。但是您不能根據 RoundEnvironment 中不相關的元素做出決定。這樣做會導致靜默失敗,因為稍後會重新編譯的檔案太少。如果您的處理器需要根據不相關元素的組合做出決定,請將其標記為「聚合」處理器。
-
他們必須為使用
Filer
API 產生的每個檔案提供一個原始元素。如果提供零個或多個原始元素,Gradle 會重新編譯所有原始檔案。
重新編譯原始檔案時,Gradle 會重新編譯從該檔案產生的所有檔案。刪除原始檔案時,會刪除從該檔案產生的檔案。
「聚合」註解處理器
這些處理器可以將多個原始檔案聚合到一個或多個輸出檔案或驗證訊息中。例如,ServiceRegistryProcessor
可以建立一個單一的 ServiceRegistry
,其中包含一個方法,對應到每個註解有 @Service
的類型。
範例:一個聚合的註解處理器
JavaFileObject serviceRegistry = filer.createSourceFile("ServiceRegistry");
Writer writer = serviceRegistry.openWriter();
writer.write("public class ServiceRegistry {");
for (Element service : roundEnv.getElementsAnnotatedWith(serviceAnnotation)) {
addServiceCreationMethod(writer, (TypeElement) service);
}
writer.write("}");
writer.close();
Gradle 會重新處理(但不會重新編譯)處理器註冊的所有註解檔案。Gradle 會重新編譯處理器產生的任何檔案。
熱門註解處理器的支援狀態
許多熱門註解處理器支援漸進式註解處理(請參閱下表)。請直接向註解處理器專案查詢以取得最新資訊和文件。 |
註解處理器 | 支援版本 | 詳細資料 |
---|---|---|
不適用 |
||
不適用 |
||
部分支援。 |
||
不適用 |
||
不適用 |
||
DataBinding |
隱藏在功能切換中 |
|
Dagger |
2.18 功能切換支援,2.24 預設啟用 |
|
kapt |
隱藏在功能切換中 |
|
Toothpick |
不適用 |
|
Glide |
不適用 |
|
Android-State |
不適用 |
|
Parceler |
不適用 |
|
Dart and Henson |
不適用 |
|
不適用 |
||
不適用 |
||
不適用 |
||
Requery |
不適用 |
|
不適用 |
||
EclipseLink |
不適用 |
|
不適用 |
||
Immutables |
不適用 |
|
2.2.0 功能切換支援,2.3.0-alpha02 預設啟用 |
||
不適用 |
||
不適用 |
||
DBFlow |
不適用 |
|
AndServer |
不適用 |
|
不適用 |
||
不適用 |
||
不適用 |
||
不適用 |
||
隱藏在功能切換中 |
||
不適用 |
避免編譯
如果依賴專案已以 ABI 相容的方式變更(僅其私有 API 已變更),則 Java 編譯工作會是最新的。這表示如果專案 A
依賴專案 B
,且 B
中的類別已以 ABI 相容的方式變更(通常僅變更方法主體),則 Gradle 就不會重新編譯 A
。
某些類型的變更不會影響公開 API,且會被忽略
-
變更方法主體
-
變更註解
-
新增、移除或變更私有方法、欄位或內部類別
-
新增、移除或變更資源
-
變更類別路徑中 jar 或目錄的名稱
-
重新命名參數
由於實作詳細資料對註解處理器很重要,因此必須在註解處理器路徑中個別宣告。Gradle 會忽略編譯類別路徑上的註解處理器。
dependencies {
// The dagger compiler and its transitive dependencies will only be found on annotation processing classpath
annotationProcessor("com.google.dagger:dagger-compiler:2.44")
// And we still need the Dagger library on the compile classpath itself
implementation("com.google.dagger:dagger:2.44")
}
dependencies {
// The dagger compiler and its transitive dependencies will only be found on annotation processing classpath
annotationProcessor 'com.google.dagger:dagger-compiler:2.44'
// And we still need the Dagger library on the compile classpath itself
implementation 'com.google.dagger:dagger:2.44'
}
變異感知選擇
整組 JVM 外掛利用 變異感知解析,針對所使用的相依項。他們也會安裝一組相容性和消歧義規則的屬性,以 設定 Gradle 屬性,針對 JVM 生態系統的特定事項。