Contents

此插件为项目增加了Java编译以及测试和打包的功能. 他提供了许多其他JVM语言Gradle 插件的基础. 你能够发现对于Java Plugin的综合介绍 - in 链接

Usage

为了使用Java 插件,包括以下到构建脚本中

  1. plugins {
  2. id 'java'
  3. }

Tasks

此插件增加了大量的任务到项目中,如下所述:

依赖: 所有贡献编译类路径的任务,包括此项目依赖的所有项目的jar 任务 ..
使用JDK 编译器编译生产Java source files

  • processResources - Copy

拷贝生产资源到生产资源目录中

  • classes

依赖: compile Java, processResources
这是一个聚合任务(仅仅依赖于其他任务),其他插件可以依附一些额外的编译任务到它 ..

依赖于: classes,以及所有共享到测试编译类路径的任务
使用JDK编译器编译测试Java source files;

  • processTestResources - Copy

拷贝测试资源到 测试资源目录中

  • testClasses

依赖于: compileTestJava,processTestResources
这是一个聚合任务 - 仅仅依赖于其他任务,其他插件也许可以依附额外的测试编译任务到它 ..

  • jar

依赖于: classes
组装可交付的Jar文件,基于依附于main 资源集(source set)的classes 以及 资源 (resources)

依赖于: classes
生成API 文档 - 使用Javadoc 为项目 ..

依赖于: testClasses,以及所有产生测试运行时类路径的任务
使用JUnit 或者TestNG 运行单元测试 …

删除项目构建目录

删除由指定的任务创建的文件, 例如cleanJar 将会删除由jar任务创建的Jar 文件 以及 cleanTest 将会删除由 test 任务创建的测试结果 …

SourceSet Tasks

对于增加到项目的每一个资源集,此插件增加了以下任务:

依赖于: 所有贡献source set的编译类路径的任务
使用JDK 编译器编译给定资源集的Java source files …

  • processSourceSetResources - Copy

拷贝给定的资源集资源到资源目录

  • sourceSetClasses - Task

依赖于 compileSourceSetJava , processSourceSetResources
预备为了打包和执行的给定资源集的classes 和资源(resources) .
某些插件也许会为给定的资源集增加额外的编译任务 .

Lifecycle Tasks

此插件也依附了一些任务到由Base Plugin 定义的生命周期任务 .. 此插件会自动应用 , 增加此插件将会自动增加少量的其他任务:

  • assemble

依赖: jar,以及创建工件依附于给定archives 配置的其他所有任务
这是一个聚合任务 组装项目中所有的归档 ,此任务由Base 插件增加 .

  • check

依赖: test
执行验证任务的聚合任务,例如运行测试,某些插件可能增加它们自己的验证任务到check. 你应该可以依附一些自定义Test任务到这个生命周期任务(在构建中如果你想要它们执行), 这个任务由Base Plugin 增加 ..

  • build

依赖: check,assemble
执行完整 项目构建的聚合任务,这个任务由Base 插件增加 ..

  • buildNeeded

依赖于: build,以及此项目的testRuntimeClasspath上的所有依赖的buildNeeded 任务..
执行此项目的完整构建 以及 它所有依赖的所有项目构建 ..

  • buildDependents

依赖于: build,所有项目的testRuntimeClasspath包含此项目依赖的所有buildDependents 任务 ..
执行此项目的完整构建以及依赖于此项目的所有项目构建 .

  • buildConfigName - task rule

依赖: 所有生成工件到给定名称为 ConfigName 的配置的任务
为给定的配置组装工件,这个规则由Base Plugin 增加 ..

  • uploadConfigName - task rule, type: Upload

依赖于: 所有生成归档文件到给定名称为 ConfigName 的配置的任务
组装并上传指定配置的工件(这个规则由 Base Plugin 增加)

图解任务依赖关系

The Java Plugin - 图1

Project layout

此插件假设项目的结构如下所示,这些目录都不需要存在或其中包含任何内容。 Java 插件将编译它找到的任何东西,并处理任何丢失的东西。

  • src/main/java

产生Java source

  • src/main/resources

产生资源,例如 XML 以及 properties files.

  • src/test/java

测试Java source .

  • src/test/resources

测试资源

  • src/sourceSet/java

指定资源集的Java source

  • src/sourceSet/resources

给定资源集的Resources

Changing the project layout

你能够配置这个项目结构 - 通过配置合适的资源集.
例如:

  1. sourceSets {
  2. main {
  3. java {
  4. srcDirs = ['src/java']
  5. }
  6. resources {
  7. srcDirs = ['src/resources']
  8. }
  9. }
  10. }

Source sets

此插件增加了以下两种 source sets

  • main

包括这个项目的生产source code ,它们将被编译并打包进Jar中 ..

  • test

包含了项目的测试代码,它们将使用Junit 或者TestNG编译并执行 .. 这些通常进行单元测试,但是它们能够包含资源集中的任务测试(只要它们共享相同的编译以及运行时类路径)

Source set properties

以下列出了资源集的重要属性,你能够在API 文档中发现更多详情 …SourceSet

  • name - (read only) String

资源集的名称,被用来标识它

资源集的输出文件,包含了它编译的文件和资源

默认值 $buildDir/classes/java/$name,例如 build/classes/java/main
这个目录生成资源集的classes,也许包含了其他JVM语言的目录 ..例如:
build/classes/kotlin/main

  • output.resourcesDir - File

默认: $buildDir/resources/$name,例如 build/resources/main
这个目录生成资源集的资源

默认值: ${name}CompileClasspath 配置 …
当编译这个资源集的源文件时所使用的类路径 …

默认是: ${name}AnnotationProcess 配置
这个处理器路径仅在编译此资源集的源文件时使用

默认为: $output,${name}RuntimeClasspath 配置
当执行这个资源集的classes时使用的类路径 ..

此资源集的Java 源文件. 仅包含.java 文件(位于 Java source 目录中) 并且排除其他所有文件 ..

  • java.srcDirs

默认值: src/$name/java,例如 src/main/java
这个资源目录包含这个资源集的Java source files .. 这个目录可以设置为任意值 ..
详情

  • java.destinationDirectory - DirectoryProperty

默认值: $buildDir/classes/java/$name,例如 build/classes/java/main
这个目录生成编译的Java sources,你能够设置为任意值详情

此资源集的资源, 仅包含资源,并且排除任何.java文件 …
其他插件,例如Groovy 插件,从此集合中排除额外的类型 ..

  • resources.srcDirs - Set

默认值: [src/$name/resources]
包含此资源集的资源的目录 …

默认值: 等同于 java 属性 …
此资源集的所有Java 文件,某些插件,例如Groovy 插件,增加额外的Java 源文件到这个集合中 ..

默认值: resources和java属性的总计(一切)
此资源集任意语言的所有源文件 .. 这包括所有资源文件以及所有Java 资源文件 …
某些插件,例如Groovy 插件, 增加一些额外的资源文件到此集合中 ..

Defining new source sets

查看 integration test example 了解更多

某些其他简单资源集的例子

增加一个包含资源集的classes的Jar

  1. tasks.register('intTestJar', Jar) {
  2. from sourceSets.intTest.output
  3. }

增加测试套件在资源集中运行测试

  1. tasks.register('intTest', Test) {
  2. testClassesDirs = sourceSets.intTest.output.classesDirs
  3. classpath = sourceSets.intTest.runtimeClasspath
  4. }

依赖管理

此插件增加了大量的dependency configurations 到项目中,例如compileJava 以及 test任务 使用一个或者多个这样的配置去获取相关的文件并使用它们 .. 例如在编译和运行时路径上进行替换 ..

Dependency configurations

为了发现api 配置中的信息,请考虑The Java Library Plugin参考文档 以及 Dependency Management for Java Projects

  • implementation

仅实现依赖项

  • compileOnly

仅编译时依赖,不在运行时使用

  • compileClasspath extends compileOnly,implementation

编译类路径,被用来编译资源,由compileJava 任务使用

  • annotationProcessor

在编译阶段使用的注解处理器

  • runtimeOnly

仅运行时依赖

  • runtimeClasspath extends runtimeOnly,implementation

包含了实现的元素,同样也包含仅运行时元素的运行时类路径 ..

  • testImplementation extends implementation

针对测试仅实现依赖 …

  • testCompileOnly

编译测试的额外依赖,不在运行时使用

  • testCompileClasspath extends testCompileOnly,testImplementation

测试编译类路径,编译测试资源时使用,由compileTestJava 使用 ..

  • testRuntimeOnly extends runtimeOnly

运行测试的仅运行时依赖

  • testRuntimeClasspath extends testRuntimeOnly,testImplementation

运行测试的运行时类路径,由test任务使用

  • archives

由此项目产生的工件(例如,jars),当构建时由Gradle 决定”default”任务执行时使用

  • default extends runtimeElements

此项目上由项目依赖所使用的默认配置,包含了工件以及此项目在运行时需要的依赖 ..
以下的表展示了main 和 test 资源集单独的依赖配置,你能够使用这个图例解释颜色:

  • 灰色的文本 - 配置不建议
  • 绿色背景 - 针对此配置声明的依赖
  • 蓝灰色的背景 - 任务消费的配置,不是你声明的依赖 ..
  • 具有淡蓝色 背景的文本 - 是一个任务 ..

    Java plugin - main source set dependency configurations

The Java Plugin - 图2

Java plugin - test source set dependency configurations

The Java Plugin - 图3
对于增加到项目的每一个资源集,此插件增加了以下的依赖配置:

SourceSet dependency configurations

  • sourceSetImplementation

给定资源集的编译时依赖,由sourceSetCompileClasspath,sourceSetRuntimeClasspath 使用 ..

  • sourceSetCompileOnly

给定资源集的仅编译时依赖,不在运行时使用

  • sourceSetCompileClasspath extends sourceSetCompileOnly,sourceSetImplementation

编译类路径,编译source时使用,由 compileSourceSetJava 使用 …

  • sourceSetAnnotationProcessor

在此资源集编译阶段使用的注解处理器

  • sourceSetRuntimeOnly

给定资源集的仅运行时依赖

  • sourceSetRuntimeClasspath extends sourceSetRuntimeOnly,sourceSetImplementation

此运行时包含了implementation的元素 同样也包含了仅运行时的元素 …

贡献扩展

此Java 插件增加了java 扩展到项目中,这允许配置大量的Java相关的属性在一个专有的DSL 块中 ..

  1. java {
  2. toolchain {
  3. languageVersion = JavaLanguageVersion.of(11)
  4. }
  5. }

当编译Java 资源时使用的Java 版本兼容能力 . 默认值: 当前使用的JVM版本 .

生成classes 文件的Java 版本,默认值 sourceCompatibility

  • withJavadocJar()

自动打包Javadoc 以及 使用一个工件 -javadoc.jar 创建一个变种 javadocElements,它们将作为发布的一部分 ..

  • withSourcesJar()

自动打包源代码并使用-sources.jar 创建一个变种 sourceElements,作为发布的一部分 …

Directory 属性

  • String reporting.baseDir

生成报告放置的目录的名称,相对于build 目录,默认值 reports

  • (read-only) File reportsDir

获取生成报告的目录,默认值 buildDir/reporting.baseDir

  • String testResultsDirName

生成的测试结果result.xml文件的放置目录名称,相对于build目录,默认值 -test-results

  • (read-only) File testResultsDir

testResultsDirName的getter,默认值 buildDir/testResultsDirName

  • String testReportDirName

生成测试报告放置的目录名称,相对于报告目录,默认值tests

  • (read-only) File testReportDir

testReportDirName的getter,默认值 reportsDir/testReportDirName

  • String libsDirName

生成库的目录名称,相对于build 目录,默认值libs

  • (read-only) File libsDir

生成库的目录,默认值 buildDir/libsDirName

  • distsDirName

生成发布的目录名称,相对于构建目录,默认值distributions

  • (read-only) File distsDir

生成库的目录, buildDir/distsDirName

  • String docsDirName

生成文档的目录名称,相对于构建目录,默认值docs

  • (read-only) File docsDir

生成文档的目录,默认值 buildDir/docsDirName

  • String dependencyCacheDirName

用来缓存资源依赖信息的目录名称,相对于构建目录,默认值: dependency-cache

Other properties

项目资源集的容器,默认值: 非空SourceSetContainer

  • String archivesBaseName

归档文件的baseName,例如Jar或者ZIP文件 .. 默认值: projectName

包括在所有Jar文件中的manifset,默认值: 一个空的manifest …

Convention properties(deprecated)

这个插件加入了大量的约定属性到项目中,你能够在构建脚本中使用这些属性 - 它们作为项目的属性 .. 这是一个废弃的且由扩展属性取代的特性.
查看 JavaPluginConvetion DSL 文档了解更多信息 …

Testing

查看Testing in Java & JVM project 了解更多 …

Publishing

  • components.java

发布一个由jar任务创建的Jar的SoftwareComponent,这个组件包含了Jar 运行时依赖信息 ..
也可以查看 java extension .

Incremental Java Compilation

从Gradle 4.7开始,增量编译器支持增量注解处理,所有的注解处理器需要加入此特性,否则它们将触发完整的重编译 ..
作为一个用户你能够看到通过 —info 日志 了解那些注解处理器触发了完全重编译 .
增量注解处理将不会被激活(如果在编译任务上配置了自定义的executable 或者javaHome)

Making an annotation processor incremental

请先查看Incremental Java compilation,因为增量注解处理构建在它之上 ..
Gradle 支持为两类常用的注解处理器实行增量构建: “隔离的isolating” 以及 “聚合的aggregating”. 请考虑以下信息决定你的处理器适用于那种分类 .
你能够为增量构建注册你的处理器 - 通过在处理器的META-INF目录中使用文件 …
这个形式是 一行一个处理器,填充完整的处理器类的名称,以及大小写不敏感的分类(通过逗号分割)
例如:

org.gradle.EntityProcessor,isolating org.gradle.ServiceRegistryProcessor,dynamic

如果你的处理器能够在运行时是否开启增量,那么你能够设置它为一个”dynamic” - 在META-INF描述符中并且在运行时返回它的正确类型(通过Processor#getSupportedOptions()方法)
例如:

  1. @Override
  2. public Set<String> getSupportedOptions() {
  3. return Collections.singleton("org.gradle.annotation.processing.aggregating");
  4. }

两种分类都有以下限制:

  • 它们必须通过Filer API生成它们的文件 .. 使用其他方式编写的文件将会导致失败,因为这些文件不会被正确清理. 如果你的处理器这样做,那么它不能是增量的 …
  • 它们必须不能依赖特定于编译器的API(例如 com.sun.source.util.Trees).Gradle 包装这些处理APIs,因此尝试强转它们为编译器指定类型将会失败 .. 如果你的处理器这样做,它不能是增量的,除非你拥有兜底机制 …
  • 如果它们使用了Filer#createResource),那么location 参数必须是来自StandardLocation的以下值:
    • CLASS_OUTPUT
    • SOURCE_OUTPUT
    • NATIVE_HEADER_OUTPUT

任何其他的参数将会禁用增量处理 ..

“Isolating” 注解处理器

这是最快的分类,它们将独立的插件每一个注解的元素 .. 为它们创建生成的文件或者验证消息 …
对于一个EntityProcessor的实例 - 通过为注解了@Entity的每一个类型创建 Repository 实例 ..
Example: An isolated annotation processor

  1. Set<? extends Element> entities = roundEnv.getElementsAnnotatedWith(entityAnnotation);
  2. for (Element entity : entities) {
  3. createRepository((TypeElement) entity);
  4. }

此类型的处理器有以下限制:

  • 它们必须做出所有的决定(代码生成,验证消息) - 从AST可达的每一个注解的类型信息做出决定,这就意味着你能够分析这些类型的超累,方法返回值,注解等等,甚至传递性 ..

但是你不能够基于RoundEnvironment的不相关的元素做出决定 .. 这样做将会导致一个错误,因为后面仅仅有一部分文件将重新编译 ..
如果您的处理器需要根据其他不相关元素的组合做出决定,那么使用”aggregating”代替 …

  • 它们必须提供准确的一个由Filer API为每一个文件生成的原始元素 ..如果提供了0个或者多个,Gradle 将会重新编译所有的源文件 …

当一个源文件被重新编译,Gradle 将会重新编译所有的由它(源文件)生成的所有文件,当一个源文件被删除时,由它生成的文件将会被删除 …

“Aggregating” annotation processor

这些能够聚合各个源文件到一个或者多个输出文件或者验证消息 ..
举个例子,一个ServiceRegistryProcessor 能够创建一个ServiceRegistry(为每一个使用@Service注解的类型)且具有一个方法

Example: An Aggreating annotation processor

  1. JavaFileObject serviceRegistry = filer.createSourceFile("ServiceRegistry");
  2. Writer writer = serviceRegistry.openWriter();
  3. writer.write("public class ServiceRegistry {");
  4. for (Element service : roundEnv.getElementsAnnotatedWith(serviceAnnotation)) {
  5. addServiceCreationMethod(writer, (TypeElement) service);
  6. }
  7. writer.write("}");
  8. writer.close();

“Aggregating” 处理器具有以下限制:

  • 它们能够读取CLASS 或者 RUNTIME 保留注解
  • 它们能够读取参数名称(如果用户使用了 -parameters 编译器参数)

Gradle 将始终重新处理(但不重新编译)处理器注册的所有带注释的文件,Gradle 将总是重新编译处理器生成的所有文件 ..

State of support in popular annotation processors

许多受欢迎的注解处理器支持增量注解构建(查看下表). 检查对应的注解处理器项目以及最新的信息和文档 …

Annotation Processor Supported since Details
Auto Value 1.6.3 N/A
Auto Service 1.6.3 N/A
Auto Value extensions Partly supported. Details in issue
Butterknife 10.2.0 N/A
Lombok 1.16.22 N/A
DataBinding AGP 3.5.0-alpha5 Hidden behind a feature toggle
Dagger 2.18 2.18 Feature toggle support, 2.24 Enabled by default
kapt 1.3.30 Hidden behind a feature toggle
Toothpick 2.0 N/A
Glide 4.9.0 N/A
Android-State 1.3.0 N/A
Parceler 1.1.11 N/A
Dart and Henson 3.1.0 N/A
MapStruct 1.4.0.Beta1 N/A
Assisted Inject 0.5.0 N/A
Realm 5.11.0 N/A
Requery Open issue N/A
EventBus 3.2.0 N/A
EclipseLink Open issue N/A
PermissionsDispatcher 4.2.0 N/A
Immutables Open issue N/A
Room 2.2.0 2.2.0 Feature toggle support, 2.3.0-alpha02 Enabled by default
Lifecycle 2.2.0-alpha02 N/A
AndroidAnnotations 4.7.0 N/A
DBFlow Open issue N/A
AndServer Open issue N/A
Litho 0.25.0 N/A
Moxy 2.0 N/A
Epoxy 4.0.0-beta1 N/A
JPA Static Metamodel Generator 5.4.11 N/A
DeepLinkDispatch 5.0.0-beta01 Hidden behind a feature toggle
Shortbread 1.1.0 N/A

编译避免

如果一个依赖的项目在ABI兼容的方式发生了改变(仅仅只有私有API发生改变). 那么Java 编译任务将会是最新的.. 这就意味着如果A依赖了B并且B中的一个类以ABI二进制兼容的方式发生了改变(通常,,改变方法的body),那么Gradle 将不会重新编译A …
有些类型的改变不会影响公共API并且它们将被忽略:

  • 改变方法体
  • 改变注释
  • 增加/移除或者改变私有方法,字段,内部类
  • 增加或者移除或者改变一个资源
  • 改变jar的名称或者类路径上的目录
  • 重命名一个参数

由于注解处理器的实现细节非常重要,它们必须在注解处理器路径上单独声明,Gradle 将在编译类路径上忽略所有的注解处理器 …

  1. dependencies {
  2. // The dagger compiler and its transitive dependencies will only be found on annotation processing classpath
  3. annotationProcessor 'com.google.dagger:dagger-compiler:2.8'
  4. // And we still need the Dagger library on the compile classpath itself
  5. implementation 'com.google.dagger:dagger:2.8'
  6. }

Variant aware selection

整套 JVM 插件利用变体感知解析来处理所使用的依赖项,他们还安装了一组属性兼容性和消歧规则,以针对 JVM 生态系统的细节配置 Gradle 属性