来!编写一个属于自己的【Gradle插件】

316 阅读4分钟

Gradle插件开发

看完本文,你会收获:

  • 可以自定义一个属于自己的【Gradle插件】!!

背景

笔者HB实习,mentor最近分配给我的任务是:

编写一个【Gradle插件】

  • 场景:A、B两个工程,其中A工程依赖了B中的某些方法/类/属性等,B修改后更新版本,但A工程的依赖并未更新,导致工程build通过但run失败
  • 用途:检测工程之间相互依赖问题(在.class文件转化.dex之间检测依赖问题,若存在,则build无法通过)

一、概述

1.1、Gradle

  • Gradle 是一款Google 推出的基于 JVM、通用灵活的项目构建工具,支持 Maven,JCenter 多种第三方仓库;支持传递性依赖管理、废弃了繁杂的xml 文件,转而使用简洁的、支持多种语言(例如:java、groovy 等)的 build 脚本文件。

二、Gradle插件

2.1、使用插件的原因

  1. 促进代码重用、减少功能类似代码编写、提升工作效率
  2. 促进项目更高程度的模块化、自动化、便捷化
  3. 可插拔式的的扩展项目的功能

2.2、分类

image

2.2.1、脚本插件

  • 脚本插件的本质就是一个脚本文件,使用脚本插件时通过apply from:将脚本加载进来就可以了,后面的脚本文件可以是本地的也可以是网络上的脚本文件,下面定义一段脚本,我们在 build.gradle 文件中使用它。
  • 示例:
def getxmlpackage(boolean x){
    def file=new File(project.getProjectDir().getPath()+"/src/main/AndroidManifest.xml");
    def paser = new XmlParser().parse(file)
    return paser.@package
}

ext{
    getpackage = this.&getxmlpackage
}
  • 使用(app moudle引用这个脚本插件)

apply from: rootProject.getRootDir().getAbsolutePath() + "/utils.gradle"

2.2.2、对象插件(核心)

二进制插件[对象插件]就是实现了 org.gradle.api.Plugin 接口的插件,每个 Java Gradle 插件都有一个 plugin id。

image

1、内部插件
1 、可通过如下方式使用一个 Java 插件:
apply plugin : 'java'    //map具名参数方式或者:

2、也可以使用闭包作为project.apply方法的一个参数
apply{
    plugin 'java'
}
  • 通过上述代码就将 Java 插件应用到我们的项目中了,对于 Gradle 自带的核心插件都有唯一的 plugin id,其中 java 是Java 插件的 plugin id,这个 plugin id 必须是唯一的,可使用应用包名来保证 plugin id 的唯一性。这里的 java 对应的具体类型是 org.gradle.api.plugins.JavaPlugin,所以可以使用如下方式使用 Java 插件:
//使用方式1:Map具名参数,全类名
apply plugin:org.gradle.api.plugins.JavaPlugin

//使用方式2 apply plugin:JavaPlugin
apply plugin: 'java'

//使用方式3:插件的id
2、第三方插件
  • 如果是使用第三方发布的二进制插件,一般需要配置对应的仓库和类路径
//使用传统的应用方式
buildscript {
    ext {
        springBootVersion = "2.3.3.RELEASE"
    }
    repositories {
        mavenLocal()
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
        jcenter()
    }
    // 此处先引入插件
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

//再应用插件
apply plugin: 'org.springframework.boot'

//社区插件,需要事先引入,不必写版本号,但是如果是第三方插件已经被托管在 https://plugins.gradle.org/ 网站上,就可以不用在 buildscript 里配置 classpath
依赖了,直接使用新出的 plugins DSL 的方式引用,案例如下: 使 用 plugins DSL 方 式
plugins {
    id 'org.springframework.boot' version '2.4.1'
}

注意:

  1. 如果使用老式插件方式buildscript{}要放在build.gradle 文件的最前面,而新式plugins{}没有该限制。
  2. 托管在网站gradle 插件官网的第三方插件有两种使用方式,一是传统的buildscript 方式,一种是 plugins DSL 方式 。
3、自定义插件【本文重点】,下面详细

三、Gradle自定义插件【重点】

接下来,直接上才艺

1、新建module,选择Java library

截屏2022-09-19 下午9.28.46.png

2、进行配置

  • 1、在/main目录下新建resources/META-INF/gradle-plugins目录(必须是这个格式!!)
  • 2、新建一个文件: 【com.example.myPlugin】.properties
     写入:implementation-class=com.example.myPlugin.MyPlugin

3、进入myPlugin的build.gradle下,加入依赖,然后同步一下(sync)

plugins {
    id 'maven-publish'  //用于上传,之后每一步都要publish一次!!!
    id 'java-library'
    id 'groovy'
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "com.android.tools.build:gradle:3.5.0"
    implementation gradleApi()
}


//定义Maven仓库信息
def MAVEN_GROUP_ID = "com.example.myPlugin"
def MAVEN_ARTIFACT_ID = "myPlugin"
def MAVEN_VERSION = "1.0"

publishing {
    publications {
        java(MavenPublication) {
            from components.java
            groupId = MAVEN_GROUP_ID
            artifactId = MAVEN_ARTIFACT_ID
            version = MAVEN_VERSION
        }
    }

    repositories {
        mavenLocal() //上传至本地的maven仓库,也可以到远程库
    }
}

4、到root目录的build.gradle下,导入依赖,再次同步一下(sync)

 dependencies {
        .....
        classpath 'com.example.myPlugin:myPlugin:1.0'
        .....
    }

5、到要引入本插件的工程的build.gradle下(笔者这里是一个android项目,就到app目录下),再次同步一下(sync)

plugins {
    ......
    id 'com.example.myPlugin'
    ......
}

6、编写插件的具体逻辑

这个部分就任意发挥的,极尽你的想象


public class NewPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {

       System.out.println("具体功能");
       // to do sth.....
    }

四、写在最后

  • 笔者最近在准备秋招,投了不下50份简历了,全部石沉大海,呜呜呜~。
  • 随后可能会更出来第二期,Gradle自定义插件 + Transform API + Java ASM整合。
  • 但是大家不要因为大环境不好就破罐子破摔,不要摆烂!不要摆烂!不要摆烂!大家加油,共勉!!!