藉助Gradle Plugin解決模組化開發中模組如何對外暴露介面

EastWoodYang發表於2018-11-30

直奔主題,在模組化開發中,模組間的資料交流大多數同學會採用以介面作為通訊協議的方式。需要面對的問題有以下幾點:

  • 介面由誰來維護?

    這個問題簡單,由提供服務的模組來維護。

  • 介面怎麼暴露?

    打成jar包,釋出到maven。

  • 介面在哪裡維護?

    現在可以參考的方案有三種:一. 所有相關模組的介面統一在一個模組中維護;二. 各個模組的介面分別在自建一個新的模組中維護,通過命名規則一一對應;三. 像微信的.api方案,使用特殊的規則混雜在各自的模組中。

    如果接著第一個問題,方案一好像就有點難確定介面對應的來源模組。方案二會出現介面模組成倍增加,極易出現一個模組只含一個介面類的現象。方案三需要自定義相關外掛,在建立介面時會有點不便,不夠靈活。


MIS登場!!!接下來先介紹mis的簡單使用以及背後的原理。

MIS

模組介面服務(Module Interface Service)

MIS是從微信的.api方案演變而來,主要解決的問題是如何在一個模組內維護其對外暴露的介面(包括打包釋出),而不是把介面和介面實現分離到兩個不同的模組。

藉助Gradle Plugin解決模組化開發中模組如何對外暴露介面

Usage

引用 mis 外掛

在根專案的build.gradle中新增mis外掛的classpath

buildscript {
    dependencies {
        ...
        classpath 'com.eastwood.tools.plugins:mis:1.3.5'
    }
}
複製程式碼

在模組的build.gradle中新增mis外掛

...
apply plugin: 'mis'
複製程式碼

建立 mis 目錄

Gradle Sync後,在java同級目錄建立mis資料夾

mis目錄

定義介面,並實現介面服務

直接在mis資料夾下,建立對應的包名、介面類和資料Model。並在java資料夾下實現介面服務。

藉助Gradle Plugin解決模組化開發中模組如何對外暴露介面

配置mis相對應的publication

mis {
    publications {
        main {
            groupId 'com.eastwood.demo'
            artifactId 'library-sdk'
            // version '1.0.0-SNAPSHOT'

            dependencies {
                compileOnly 'com.google.code.gson:gson:2.8.1'
            }
        }
    }
    ...
}
複製程式碼
  • main指的是src/main/java中的main,除了main之外,其值還可以為 build types和product flavors對應的值,即對應目錄下的mis。比如與src/debug/java對應的src/debug/mis

  • groupIdartifactIdversion對應的是Maven的GAV初次配置時不設定version,釋出至maven時設定version

  • dependencies中可宣告該mis編譯和執行時需用到的第三方庫,僅支援compileOnlyimplementation

釋出至Maven

mis {
    publications {
        main {
            groupId 'com.eastwood.demo'
            artifactId 'library-sdk'
            version '1.0.0-SNAPSHOT'
            ...
        }
    }

    repositories {
        maven {
            url "http://***"
            credentials {
                username '***'
                password '***'
            }
        }
    }
    ...
}
複製程式碼
  • 釋出時需設定version

  • 釋出時內部用到的外掛是maven-publish,其中repositories相關設定請查閱# Maven Publish Plugin

Gradle Sync後,開啟Gradle Tasks View,選擇publishMis[...]PublicationToMavenRepository執行釋出任務。

上傳Task

其中publishMis[...]PublicationToMavenLocal 是釋出至本地maven。如果使用本地maven,請將mavenLocal()新增至根專案的build.gradle中,比如:

allprojects {
    repositories {
        google()
        jcenter()
        mavenLocal()
    }
}
複製程式碼

Q&A

1.mis目錄下的類會參與編譯嗎?

不會。雖然mis目錄下的類能被java目錄下的類直接引用,但不會參與編譯,真正參與編譯的是該mis目錄生成的jar包,其位於當前工程.gradle/mis下。在當前工程Sync&Build的時候,mis外掛會對這些配置了publication的mis目錄進行編譯打包生成jar包,並且依賴該jar包。

mis目錄下的類之所以能被java目錄下的類直接引用,是因為mis目錄被設定為sourceSets aidl的src目錄,而Android Studio對sourceSets aidl的src目錄有特別支援。

2.沒有Maven私服,所有模組都在一個工程下,其他模組怎麼引用介面?

不設定publicationversion。通過misPublication宣告依賴,比如:

dependencies {
    ...
    implementation misPublication('com.eastwood.demo:library-sdk')
}
複製程式碼

misPublication執行機理是會自動在當前工程.gradle/mis下查詢是否有對應的mis提供的jar包。如果有,就使用對應的mis提供的jar包;如果沒有且指定了version,就使用maven上的jar包。

3.將介面釋出到maven後,其他模組通過misPublication宣告依賴,那jar包用的是.gradle/mis下的還是maven上的?

介面被髮布到maven後,其.gradle/mis下的jar包會被刪除,介面所在的模組根據publication中設定的GAV使用maven上的jar包。如果其他模組通過misPublication宣告對其依賴,比如:

dependencies {
    ...
    implementation misPublication('com.eastwood.demo:library-sdk')
    // 或 implementation misPublication('com.eastwood.demo:library-sdk:1.0.0-SNAPSHOT')
}
複製程式碼

不管misPublication中是否設定了的version,都會使用maven上的jar包,其版本同介面所在的模組publication中的GAV。

mis目錄下類發生實質性的修改後(生成不同的jar包),在當前工程Sync&Build的時,會在.gradle/mis下的重新生成jar包,介面所在的模組不管publication中是否設定version,都使用.gradle/mis下的jar包。如果其他模組通過misPublication宣告對其依賴,不管misPublication中是否設定的version,都會使用.gradle/mis下的jar包。

4.為什麼在Gradle Tasks View中找不到publishing相關釋出Task?

初次釋出時,請檢查對應的publication是否已經設定的version,以及是否新增相關repositories


最後

MIS已經上傳至Github,歡迎star交流。QQ 1056453754

github.com/EastWoodYan…

相關文章