Gradle实战1-微信Tinker项目中的maven-publish封装

1,288 阅读4分钟

引言

前面我们学习了Groovy语言,Gradle相关知识(如:生命周期/project/task等)

了解到了Gradle是一个很好用的构建工具,具体细节可以自行回顾往期文章:

1)【Gradle系列】初识Gradle

2)【Gradle系列】Groovy语法之变量定义

3)【Gradle系列】Groovy基础编程知识1

4)【Gradle系列】Groovy基础编程知识2

5)【Gradle系列】Gradle的生命周期

6)【Gradle系列】Gradle 之Project详解(一)

7)【Gradle系列】Gradle之Project详解(二)

8)【Gradle系列】Gradle之 Project详解(三)

9)【Gradle系列】Gradle之Task

10)【Gradle系列】Gradle在Android上的拓展

接下来,我们将用前面学习的理论,逐步用到实战中去

背景

日常开发中,我们如果开发了一个基础组件,都会通过maven来发布到远程或者本地,来提供给业务开发的同学使用;

如果基础组件比较多的时候,那么上传脚本的通用性就必须要考虑了,因为不可能再每一个基础组件的项目中,都重复写上传的脚本;

所以接下来,我们将利用前面学过的知识(如:gradle属性拓展/生命周期等)来实现maven上传的通用脚本;

另外,基于方案的科学性/实用性方面考虑,本章将通过研究微信Tinker项目中的maven-publish封装来开展

实现的效果

1)根工程的gradle

1.png

在上传maven的时候,一般要指定上传的地点/组件的版本号/组件名称等信息

这些是输入信息,会根据不同开发者/企业等的不同而改变,属于配置信息

所有需要抽到指定的地方(如:根工程的gradle文件/单独的配置文件等),这里我们 放在了根工程的gradle中

上图可以看出我们配置了的信息有:

VERSION_NAME = '1.0.666'
GROUP = 'com.davi.mavenPlu'
// 会在项目根目录生成文件夹
POM_URL = 'file:daviRepoMaven666'

其中,我们上传到本地仓库(即特定的文件夹中)

2)组件工程的gradle

1.png

这里我们是一个java的组件(java工程模块),在输出jar后上传到本地仓库;

这里是使用《maven-publish封装》的地方,可以看出我们引入了通用封装好的脚本:

apply from: rootProject.file('daviGradle/DaviPublish.gradle')

使用的时候,比较简单:

1)daviPublish,自定义的拓展标示,代表发布maven

2)pom,自定义的拓展,代表要发布的内容

3)publishToMaven,自定义的拓展,代表要发布的地址

3)通用封装好的脚本

在第2点中,封装好的脚本位置如下:

3.png 细节先不在这里展开

4)运行效果

通过前面的3步之后,执行task就可以实现java组件的上传,具体效果如下:

4.png

除此之外,无论下次是任何java组件需要上传,只需要简单的配置即可(也就是第1和第2点) 然后引用下第3点这个封装好的《maven-publish封装》即可,比如微信Tinker项目中的复用效果:

2.png

《maven-publish封装》具体实现

// Register  extension
extensions.create('daviPublish', JavaLibraryPublishExtension.class, project)
//ext.artifactId = name

/**
 *
 * 基于《maven-publish》方式的上传java工程的jar
 *
 * */
class JavaLibraryPublishExtension {

    private final Project project

    protected final ArrayList<Closure> pomClosures = []

    private final ArrayList<Closure> mavenPublishClosures = []

    JavaLibraryPublishExtension(Project p) {
        project = p

        //执行阶段 publish
        p.afterEvaluate {
            this.publish()
        }
    }

    protected void publish() {
        //强校验
        //因为这个功能是基于'maven-publish'的通用设计
        if (!project.plugins.hasPlugin('maven-publish')) {
            project.plugins.apply('maven-publish')
        }

        emitPublicationDSL(project)

        emitRepositoryDSL(project)
    }

    /**
     * 要发布的内容准备(如:java源码/javaDoc等)
     * */
    protected void emitPublicationDSL(Project project) {
        /***
         * 获取源码的task
         * */
        def sourcesJarTask = project.task('sourcesJar', type: Jar) {
            classifier = 'sources'
            //project.sourceSets.main 中的代码的位置目录保存起来,输出到 srcDirs = []
            def srcDirs = []
            def sources = project.sourceSets.main
            ['java', 'groovy', 'scala', 'kotlin'].each {
                if (sources.hasProperty(it)) {
                    println "获取源码的task : project.sourceSets.main has ${it}"
                    srcDirs << sources[it].srcDirs
                }
            }
            from srcDirs
        }


        /***
         * maven 要发布的内容(可配置多个)
         *
         * 发布:sourcesJarTask的源码
         * */
        project.publishing.publications {
            //${publicationName},称为发布组件Component,用于配置一项要发布的内容
            //只是一个命名,并无特殊含义(也可以将其更换为别的名称,但不能与其它发布组件名称重复)
            "${publicationName}"(MavenPublication) {
                from project.components.java
                groupId this.groupId
                version this.version
                //将 sourcesJarTask 看作 artifact,交给 archives 管理
                //artifact sourcesJarTask
            }
        }

        /**
         * maven 要发布的内容(可配置多个)
         * 外部传进来的pom
         * */
        pomClosures.each { cl ->
            //要发布的内容(可配置多个)
            project.publishing.publications {
                "${publicationName}"(MavenPublication) {
                    // 闭包存到 pomClosures数组
                    pom cl
                }
            }
        }
    }

    /**
     * 要发布的地点
     * */
    private void emitRepositoryDSL(Project project) {
        mavenPublishClosures.each { cl ->
            project.publishing.repositories {
                maven {
                    cl.delegate = delegate
                    cl()
                }
            }
        }
    }

    String getGroupId() {
        return project.group
    }

    String getVersion() {
        return project.version
    }

    final protected String getPublicationName() {
        return project.name
    }

    /***
     * 自定义拓展属性 pom
     * */
    void pom(Closure cl) {
        if (cl != null)
            pomClosures << cl
    }

    /***
     * 自定义拓展属性 publishToMaven
     * */
    void publishToMaven(Closure cl) {
        if (cl != null)
            mavenPublishClosures << cl
    }

}

源码地址

github.com/zgxzgxzg/Da…

结尾

哈哈,该篇就写到这里(一起体系化学习,一起成长)

Tips

更多精彩内容,请关注 “Android热修技术” 微信公众号