Gradle学习(二十二)——使用Gradle插件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lastsweetop/article/details/79643576

Gradle的核心并没有为构建的自动化提供太多直接的帮助,更多的特性是由插件完成的。比如编译java代码也是由插件完成的。插件可以增加新的任务(比如JavaCompile),domain对象(比如SourceSet),约定(比如,java代码放在src/main/java),以及一些其他的对象,也包括从其他插件扩展出来的对象。

插件的作用

把插件应用到项目中可以扩展项目的功能,它可以做以下事情:

  • 扩展Gradle模型(比如增加了可以配置的新的DSL元素)
  • 根据约定配置项目(增加新的任务或者配置合理的默认值)
  • 应用特定的配置(增加有组织的存储库或者执行标准)

通过应用插件比直接通过构建脚本来实现的好处多多,比如:

  • 提高重用性,减少在多个项目中相同构建逻辑的维护开销
  • 更高程度的模块化,使得更加易于理解,更加容易组织
  • 封装必要性的逻辑,构建脚本只用于声明定义

插件的类型

在Gradle中有两种插件:脚本插件和二进制插件。脚本插件是额外的构建脚本,进一步配置构建,常常用于声明一些操作构建的方法,它们通常在构建内部使用。二进制插件是实现了Plugin的类,并且通过编程方式来操作构建,二进制插件可以在构建脚本中,也可以在buildSrc中,也可以以jar的方式导入。

插件通常开始只是一个脚本插件,但是随着代码价值的增加,便会迁移成二进制插件,以便分享出来给其他人使用

使用插件

要想使用插件的封装逻辑,只需两步就可以,第一步解析插件,第二步把插件应用到目标中,目标通常就是项目。

解析插件意思就是找到给定包含插件的jar的正确版本,并把它添加到脚本的classpath中,一旦插件被解析,它的API就能在构建脚本中使用,脚本插件可以以应用它们的文件路径和URL自解析,核心的二进制插件作为Gradle的一部分来自动解析。

应用插件实际上就是在应用插件的项目上执行插件的Plugin.apply(T)方法。应用插件的是idempotent的,也就是你可以多次应用任意插件。

使用插件最常见的用例就是解析插件并将它应用到当前项目。用于这是最常见的用例,因此建议构建脚本的编写者,一步就可以包含这两个步骤。

脚本插件

apply from: 'other.gradle'

脚本插件是可以自动解析的,它可以是相对于项目目录的本地路径,也可以是个http的远程路径,

二进制插件

你可以通过插件的id来应用插件,对插件来说id是唯一标识符,同时也是插件的名字。Gradle的核心插件比较特殊,你只需提供id的简称就可以,比如核心javaPlugin,使用简称java就可以引入,但是对于之外的二进制插件则必须使用全称,比如com.github.foo.bar

扫描二维码关注公众号,回复: 3298625 查看本文章

二进制插件的位置

插件简单的说就是实现了Plugin接口的类,Gradle将核心插件作为发布的一部分提供出来,这意味着核心插件可以自动解析。但是非核心的二进制插件就需要在应用之前得到解析,它通常通过下面几种方式实现:

  • 从插件的官网或者自定义的资源库中通过插件的DSL将插件包含进来
  • 通过构建脚本的依赖通过额外的jar将插件包含进来
  • 定义插件作为项目的buildSrc目录的源文件
  • 定义插件作为项目构建脚本的内部类

通过插件的DSL应用插件

新的插件DSL提供一种简洁而方便的定义插件依赖的方法,它和Gradle的插件官网一起工作,可以非常方便的访问核心库和社区库的插件。插件的DSL代码块其实是在配置PluginDependenciesSpec实例。

使用核心插件可以使用简称

plugins {
    id 'java'
}

如果从插件官网使用社区版插件,就需要使用全称了

plugins {
    id 'com.jfrog.bintray' version '0.4.1'
}

插件DSL的局限性

这种添加插件的方法不至于方便,插件DSL的处理方法可以更早更快的解析插件,使得Gradle可以做一些聪明的事情:

  • 优化插件类的加载和重用
  • 允许不同插件使用不同版本的依赖
  • 可以提供给编辑器更多潜在的属性和值的信息,以增加编写构建脚本时的编辑上的帮助

在执行剩余的构建脚本之前,它需要在这种方式下更早更快的指定插件,它也需要插件的定义在某种程度上是静态的

语法约束

新的plugins{}块并不支持所有的groovy代码,它的约束是为了幂等(每次都产生相同的结果)的和无副作用(在任何时候都是安全的)

格式如下:

plugins {
    id «plugin id» version «plugin version» [apply «false»]
}

«plugin version»«plugin id»必须是常量,文字或字符串,apply则必须是bool类型(可以用于快速禁用插件),如果写了其他之外的语句,将会引起编译错误。

plugins {}在构建脚本中还需要是顶级语句,不能嵌套在其他结构内部,比如if-esle条件结构或者for循环结构。

仅仅可以使用在构建脚本中

plugins {}目前仅仅可以使用在构建脚本中,而不能使用在脚本插件,settings.gradle和初始化脚本。

把插件应用到子工程中

在多项目构建中,你可能想吧插件应用到一部分或者所有的子项目,而不是根项目,plugins {}默认的行为是快速解析和应用插件,但是你可以通过apply false来告诉Gradle不要应用插件,然后通过apply plugin: «plugin id»应用到子项目中。

settings.gradle

include 'helloA','helloB','goodbyeC'

build.gradle

plugins {
    id 'com.lastsweetop.plugin.greeting' version '0.4' apply false
    id 'com.lastsweetop.plugin.goodbye' version '0.4' apply false
}

subprojects { subproject ->
    if (subproject.name.startsWith('hello')) {
        apply plugin: 'com.lastsweetop.plugin.greeting'
    }
    if (subproject.name.startsWith('goodbye')) {
        apply plugin: 'com.lastsweetop.plugin.goodbye'
    }
}

如果你运行gradle hello你将会看到只有helloAhelloB两个子项目应用了greeting插件

± % gradle hello                                                                 

> Task :helloA:hello
Hello from the GreetingPlugin

> Task :helloB:hello
Hello from the GreetingPlugin


BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed

自定义插件资源库

默认情况下,plugins {}DSL将会从Gradle插件官网下载插件,但很多构建者想从自己的私有Maven仓库下载Gradle插件,因为可能需要私有的实现细节,而且可以更好的控制插件的可用性。

为了指定自定义的插件资源库,需要在settings.gradle中使用pluginManagement {}下嵌套的repositories {}

pluginManagement {
    repositories {
        maven {
            url 'http://127.0.0.1:8081/repository/sweetop/'
        }
        gradlePluginPortal()
    }
}

这会告诉Gradle首先在http://127.0.0.1:8081/repository/sweetop/资源库中查找,如果没有找到然后才会寻找官方的插件资源库,如果你不想寻找官方资源库,可以去掉gradlePluginPortal()

插件解析规则

插件解析规则允许你修改插件在plugins {}块中的请求模式,比如修改插件请求的版本或者明确指定实现插件的工件位置。

为了修改解析规则,你需要在pluginManagement {}中使用resolutionStrategy {}

pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.namespace=="com.lastsweetop.plugin") {
                useModule('com.lastsweetop.plugin:helloPlugin:0.4')
            }
        }
    }
    repositories {
        maven {
            url 'http://127.0.0.1:8081/repository/sweetop/'
        }
        gradlePluginPortal()
    }
}

这会明确指定插件需要的jar,而不是插件内部指定的jar坐标。

pluginManagement {}块必须出现在settings.gradle文件中,而且必须是文件的第一个块,自定义的Maven资源库中必须包含插件标记工件。

插件标记工件

由于plugins {}的DSL块只定义了插件的id和版本,Gradle需要一种方式可以查找实现了插件的工件,Gradle会以plugin.id:plugin.id.gradle.plugin:plugin.version这样的格式去匹配插件标记工件,这个标记工件依赖于实际的插件实现,而且是由java-gradle-plugin来发布的。

例如,helloPlugin项目会使用maven-publish插件和java-gradle-plugin插件的组合将com.lastsweetop.plugin.greetingcom.lastsweetop.plugin.goodbye插件发布到Maven仓库中,

apply plugin: 'groovy'
apply plugin: 'maven-publish'
apply plugin: 'java-gradle-plugin'

gradlePlugin {
    plugins {
        hello {
            id = "com.lastsweetop.plugin.greeting"
            implementationClass = "com.lastsweetop.plugin.GreetingPlugin"
        }
        goodbye {
            id = "com.lastsweetop.plugin.goodbye"
            implementationClass = "com.lastsweetop.plugin.GoodbyePlugin"
        }
    }
}

publishing {
    repositories {
        maven {
            url "http://127.0.0.1:8081/repository/sweetop/"
            credentials {
                username 'admin'
                password 'admin123'
            }
        }
    }
}

运行gradle publish会在maven资源库产生如下的资源样式:
nexus-layout

使用buildscript应用插件

二进制插件可以被发布成外部的jar文件,然后通过将其增加到构建脚本的classpath中来进一步应用插件。外部的jar想要添加到构建脚本的classpath中需要使用buildscript {}

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1"
    }
}

apply plugin: "com.jfrog.bintray"

猜你喜欢

转载自blog.csdn.net/lastsweetop/article/details/79643576