Java 插件是构建 JVM 项目的基础,它为项目增加了很多能力,例如编译,测试,打包,发布等等。
很多插件都是基于 Java 插件实现的,例如 Android 插件。
使用 id 应用插件
plugins { id 'java' }
Java 插件引入了源集的概念,它在逻辑上表示一组用于编译执行的源文件,这些源文件可能包括源代码文件和资源文件。
一个源集有一个相关联的编译类路径和运行时类路径。
Java 插件就是通过源集的概念来管理源代码目录的。
源集的一个用途是,把源文件进行逻辑上的分组,以描述它们的目的。
例如,你可能会使用一个源集来定义一个集成测试套件,或者你可能会使用单独的源集来定义你的项目的 API 和实现类。
Java 插件提供了两个标准源集
源集提供了很多属性,我这里就列出几个重要的属性:
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
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] | 源集的资源目录,是一个集合,可以指定多个 |
跟多的源集属性可以查看下面的文档
sourceSets DSL
sourceSets API
源集的位置也很重要,不要在 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' }
创建一个 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 }
创建一个任务将源集的所有 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 插件都会为它增加下面列出的任务:
compile sourceSet Java JavaCompile
依赖:所有有助于源集编译类路径的任务。
功能:使用 JDK 编译器编译给定源集的 Java 源文件
process sourceSet Resources Copy
功能:复制给定源集的资源到资源目录
sourceSet Classes Task
依赖:compile sourceSet Java , process sourceSet Resources
功能:准备给定的源集的类和资源以进行打包和执行。一些扩展插件可能会为给定源集附加编译任务到这里
Java 插件将它的一些任务附加到基础插件(Java插件自动应用)定义的生命周期任务上。
它还添加了一些其他的生命周期任务:
assemble
依赖:jar, 以及创建附加到归档配置的工件的所有其他任务。
汇总项目中所有归档的聚合任务。 这个任务是基础插件(Base)里定义的。
check
依赖:test
汇总项目中的验证任务,例如运行测试。一些插件会增加自己的验证任务到这里。这个任务是基础插件(Base) 里定义的。
build
依赖:check, assemble
聚合执行项目完整构建的任务。这个任务是基础插件(Base) 里定义的。
buildNeeded
依赖:build ,以及在testRuntimeClasspath配置中依赖的所有项目中的buildNeeded任务。
执行项目本身及其依赖的所有项目的完整构建。
buildDependents
依赖:build, 以及在 testRuntimeClasspath 配置中依赖此项目的所有项目的 buildDependents 任务
执行项目本身以及依赖于它的所有项目的完整构建。
build ConfigName -任务规则
依赖:生成附加到命名- ConfigName -配置的工件的所有任务
为指定的配置组装工件。这个规则是在基础插件增加的。
upload ConfigName -任务规则,类型: 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 sourceSet Compile | 实现给定源集的依赖性。由 sourceSet CompileClasspath, sourceSet RuntimeClasspath 使用。 |
sourceSet CompileOnly | 给定源集的编译时依赖,只能在编译时使用。 |
sourceSet CompileClasspath extend compile sourceSet Java | 当编译源代码时的编译类路径,被 sourceSet Compile, sourceSet CompileOnly, sourceSet Implementation 使用。 |
sourceSet AnnotationProcessor | 给定源集在编译时使用的注解处理器 |
|
给定源集的运行时依赖,由 sourceSet RuntimeOnly 取代 |
sourceSet RuntimeOnly | 给定源集的运行时依赖,仅仅是运行时的 |
sourceSet RuntimeClasspath extends sourceSet RuntimeOnly , sourceSet Runtime, sourceSet Implementation | 给定源集的运行时类路径,包含 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