Java 插件是构建 JVM 项目的基础,它为项目增加了很多能力,例如编译,测试,打包,发布等等。
很多插件都是基于 Java 插件实现的,例如 Android 插件。
用法
使用 id 应用插件
plugins {
id 'java'
}
Source sets 源集
Java 插件引入了源集的概念,它在逻辑上表示一组用于编译执行的源文件,这些源文件可能包括源代码文件和资源文件。
一个源集有一个相关联的编译类路径和运行时类路径。
Java 插件就是通过源集的概念来管理源代码目录的。
源集的一个用途是,把源文件进行逻辑上的分组,以描述它们的目的。
例如,你可能会使用一个源集来定义一个集成测试套件,或者你可能会使用单独的源集来定义你的项目的 API 和实现类。
Java 插件提供了两个标准源集
- main 包含了项目的源代码,被用于编译和生成 JAR 文件
- test 包含单元测试源代码,它们将被编译并使用 JUnit 或 TestNG 来执行。
源集提供了很多属性,我这里就列出几个重要的属性:
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
name - 只读 | String | 非空 | 源集的名字 |
output - 只读 | SourceSetOutput | 非空 | 源集的输出文件,包括它编译过的类和资源。 |
output.classesDirs 只读 | FileCollection | $buildDir/classes/java/$name 例如:build/classes/java/main |
源集编译过的 class 文件目录 |
output.resourcesDir 只读 | File | $buildDir/resources/$name例如main源集:build/resources/main | 源集产生的资源目录 |
java - 只读 | SourceDirectorySet | [${project.projectDir}/src/${sourceSet.name}/java] | 源集的 Java 源代码 ,只包含 .java 会排除其他类型。 |
java.srcDirs | Set |
src/$name/java, 例如 src/main/java |
源集的 Java 源文件的源目录。是一个集合,可以设置多个源代码目录,更改源代码目录就是更改这个属性 |
java.outputDir | File | $buildDir/classes/java/$name, e.g. build/classes/java/main |
源代码编译的 class 文件输出目录 |
resources - 只读 | SourceDirectorySet | [${project.projectDir}/src/${sourceSet.name}/resources] | 源集的资源,只包含资源。 |
resources.srcDirs | Set |
[src/$name/resources] | 源集的资源目录,是一个集合,可以指定多个 |
跟多的源集属性可以查看下面的文档
定义一个新的源集
源集的位置也很重要,不要在 dependencies
下面,否则对源集的依赖就将不起作用
sourceSets {
other
}
访问源集
sourceSets 是 Java 插件为 Project 增加的一个属性,可以直接使用。
task outSourceSet {
doLast {
//遍历
sourceSets.all {
println "$name -> "
}
println "-----分割线----"
//单个的
println "${sourceSets.main.name} -> "
println "${sourceSets['main'].name} -> "
//一些属性
println " java.srcDirs -->${sourceSets.main.java.srcDirs}"
println " resource.srcDirs -->${sourceSets.main.resources.srcDirs}"
}
}
为源集添加依赖
dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:27.1-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
//为 other 源集添加依赖
otherImplementation 'com.google.code.gson:gson:2.8.5'
}
将源集打成一个 JAR 包
创建一个 otherJar 任务,将源集的输出作为任务的文件来源。
执行这个任务即可生成 JAR 包。
/**
* 为 other 源集打个 jar 包
* 默认输出目录是 build/libs
* 默认名字是 [archiveBaseName]-[archiveAppendix]-[archiveVersion]-[archiveClassifier].[archiveExtension]
*/
task otherJar(type:Jar){
archiveBaseName = sourceSets.other.name
archiveVersion = '0.1.0'
destinationDirectory = file("${project.projectDir}/jar")
from sourceSets.other.output
}
为源集生成 doc
创建一个任务将源集的所有 Java 文件作为源文件。
执行这个任务即可生成 doc 文件。
task otherDoc(type:Javadoc){
destinationDir = file("${project.projectDir}/doc")
source sourceSets.other.allJava
title sourceSets.other.name
}
项目结构
Java 插件的默认目录结构如下所示, 无论这些文件夹中有没有内容, Java 插件都会编译里面的内容, 并处理没有的内容。
这个目录结构也是 Java 世界标准的项目目录。
目录 | 描述 |
---|---|
src/main/java | Java 源文件目录 |
src/main/resources | 资源文件目录,例如 xml 和 properties 文件 |
src/test/java | Java 测试源文件目录 |
src/test/resources | 测试资源目录 |
src/sourceSet/java | 给定源集的源代码目录 |
src/sourceSet/resources | 给定源集的资源目录 |
更改默认目录
这里以更改 main 源集的源代码和资源目录为例
sourceSets {
main {
java {
srcDirs = ['src/java']
}
resources {
srcDirs = ['src/resources']
}
}
}
增加的任务
Java 插件为 Project 增加了很多实用的任务,如下:
-
compileJava 类型是 JavaCompile
依赖于:所有参与编译类路径的任务,包括 jar 任务和通过项目依赖性在类路径上的项目中的任务。
功能:使用 JDK 编译器编译生产 Java 源文件。
-
processResources Copy
功能:复制生产资源到资源目录
-
classes
依赖:compileJava , processResources
这是个整合的任务,只是依赖于其他任务。其他插件可能会附加别的编译任务到这里。
-
compileTestJava JavaCompile
依赖:classes, 以及有助于测试编译类路径的所有任务
功能:使用 JDK 编译器编译测试 Java 源代码和资源文件
-
processTestResources Copy
功能:复制测试资源到测试资源目录
-
testClasses
依赖:compileTestJava , processTestResources
这是个整合任务,只是依赖其他任务。其他扩展插件可能会将测试编译任务附加到这里。
-
jar Jar
依赖:classes
功能:根据主源集的类和资源,组装生产 JAR 文件。
-
javadoc JavaDoc
依赖:classes
功能:生成 API 文档。
-
test Test
依赖:testClasses 以及生成测试运行时类路径的所有任务
功能:使用 JUnit 或者 TestNG 运行单元测试
-
uploadArchives Upload
依赖:jar 以及生辰附加在 archives{} 配置里的构件的任何其他任务。
功能:上传 archives{} 配置里的构件包含生成的 JAR 文件到配置的仓库。
-
clean Delete
功能:删除项目构建目录
-
clean[TaskName] Delete
功能:删除由指定任务生成的文件。例如 cleanJar 将删除由 jar 任务产生的文件。
源集任务
你增加的每一个源集,Java 插件都会为它增加下面列出的任务:
-
compilesourceSetJava JavaCompile
依赖:所有有助于源集编译类路径的任务。
功能:使用 JDK 编译器编译给定源集的 Java 源文件
-
processsourceSetResources Copy
功能:复制给定源集的资源到资源目录
-
sourceSetClasses Task
依赖:compilesourceSetJava , processsourceSetResources
功能:准备给定的源集的类和资源以进行打包和执行。一些扩展插件可能会为给定源集附加编译任务到这里
生命周期任务
Java 插件将它的一些任务附加到基础插件(Java插件自动应用)定义的生命周期任务上。
它还添加了一些其他的生命周期任务:
-
assemble
依赖:jar, 以及创建附加到归档配置的工件的所有其他任务。
汇总项目中所有归档的聚合任务。 这个任务是基础插件(Base)里定义的。
-
check
依赖:test
汇总项目中的验证任务,例如运行测试。一些插件会增加自己的验证任务到这里。这个任务是基础插件(Base) 里定义的。
-
build
依赖:check, assemble
聚合执行项目完整构建的任务。这个任务是基础插件(Base) 里定义的。
-
buildNeeded
依赖:build ,以及在testRuntimeClasspath配置中依赖的所有项目中的buildNeeded任务。
执行项目本身及其依赖的所有项目的完整构建。
-
buildDependents
依赖:build, 以及在 testRuntimeClasspath 配置中依赖此项目的所有项目的 buildDependents 任务
执行项目本身以及依赖于它的所有项目的完整构建。
-
buildConfigName -任务规则
依赖:生成附加到命名- ConfigName -配置的工件的所有任务
为指定的配置组装工件。这个规则是在基础插件增加的。
-
uploadConfigName -任务规则,类型:Upload
依赖:生成附加到命名- ConfigName -配置的工件的所有任务
在指定的配置里组装和上传构件。这个规则是在基础插件增加的。
下面的图展示了这些任务的关系
依赖管理
Java 插件增加了很多依赖配置到项目中,JavaCompile 和 test 任务就可以使用这些配置将依赖文件添加到类路径并使用他们。
依赖配置 | 描述 |
---|---|
编译时依赖,被 implementation 取代 | |
implementation 继承自compile | 仅实现依赖性。 |
compileOnly | 仅仅编译时依赖 运行时不能用 |
compileClasspath 继承自 compile,compileOnly,implemenation | 当编译源代码时使用的编译类路径,被 compileJava 任务使用 |
annotationProcessor | 编译时使用的注解处理器 |
运行时依赖,由 runtimeOnly 取代 | |
runtimeOnly | 仅运行时依赖,编译时不能用 |
runtimeClasspath 继承自 runtimeOnly,runtime,implementation | 运行时类路径包含 implementation 和仅运行时的元素 |
测试编译的依赖项,被 testImplementation 取代 | |
testImplementation 继承自 testCompile,implemenation | 仅实现测试依赖 |
testCompileOnly | 编译时测试依赖,仅仅只在编译时 |
testCompileClasspath 继承自 testCompile ,testCompileOnly ,testImplementation | 测试编译类路径,当编译测试代码的时由 compileTestJava 任务使用 |
测试运行时依赖,由 testRuntimeOnly 取代 | |
testRuntimeOnly 继承自 runtimeOnly | 测试的运行时依赖 |
testRuntimeClasspath 继承自 testRuntimeOnly,testRuntime,testImplementation | 运行测试的运行时类路径,由 test 任务使用 |
archives | 项目产生的构件(例如 jar),由 uploadArchives 使用 |
下面两张图是 main 和 test 源集的配置依赖关系
- 灰色字体:已废弃的
- 黑色字体绿色背景:可以根据配置声明依赖项。
- 灰蓝背景: 该配置用于被任务使用,而不是用于声明依赖项。
- 浅蓝色背景:任务
除了以上的配置,Java 插件为了每个源集还添加了以下配置,这些配置只针对给定源集
依赖配置 | 描述 |
---|---|
给定源集的编译时依赖,由 sourceSet Implementation 取代 | |
sourceSet Implementation extend sourceSetCompile | 实现给定源集的依赖性。由 sourceSetCompileClasspath, sourceSetRuntimeClasspath 使用。 |
sourceSetCompileOnly | 给定源集的编译时依赖,只能在编译时使用。 |
sourceSetCompileClasspath extend compilesourceSetJava | 当编译源代码时的编译类路径,被 sourceSetCompile,sourceSetCompileOnly,sourceSetImplementation 使用。 |
sourceSetAnnotationProcessor | 给定源集在编译时使用的注解处理器 |
给定源集的运行时依赖,由 sourceSetRuntimeOnly 取代 | |
sourceSetRuntimeOnly | 给定源集的运行时依赖,仅仅是运行时的 |
sourceSetRuntimeClasspath extends sourceSetRuntimeOnly ,sourceSetRuntime,sourceSetImplementation | 给定源集的运行时类路径,包含 implement 和 runtime 的元素。 |
增加的属性
Java 插件为项目增加了很多新的属性,可以在脚本中直接使用这些属性。
下面是一些我认为比较重要的属性:
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
sourceSets 只读 | SourceSetContainer | 非空 | 包含项目的源集 |
sourceCompatibility | JavaVersion | 当前 JVM 的版本 | 编译 Java 源代码时使用的 Java 版本,可以是一个 数值或者字符串,例如 '1.8' 或者 1.8 |
targetCompatibility | JavaVersion | sourceCompatibility | 生成 class 文件的版本,可以是一个 数值或者字符串,例如 '1.8' 或者 1.8 |
archivesBaseName | String | 归档的文件使用的名字,例如 JAR 和 ZIP 文件 | |
manifest | Manifest | 一个空的清单 | 包含所有 JAR 文件的清单。 |
libsDirName | String | libs | 项目生成的库的存放目录,项目的相对路径。 |
更多的属性可以查看文档 Convention properties