gradle是如何用插件id找到插件的?
我们在使用gradle的过程中,多少都会有个疑问,就是插件的写法与依赖的写法为什么不太一样?
插件的写法:
plugins {
java
id("org.springframework.boot") version "3.5.7"
id("io.spring.dependency-management") version "1.1.7"
}
依赖的写法:
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
}
其中依赖的写法对应经典的maven依赖的三段定义方式,在有依赖管理的情况下,可以省略版本号。插件中java这种核心插件因为内置在gradle本身之中,可以简化处理也不奇怪。但spring boot这种三方插件的写法就跟依赖不太一样。
如果说插件跟依赖本来就是两种东西,存在不同的库中,gradle爱怎么管理都行。但实际上他们又都可以存在maven仓库中。开发时只能用公司私服不能连外网的朋友肯定深有体会,插件和依赖其实都是在一个仓里的。
既然如此,我们就要问了,gradle插件放在maven仓库里,写法有不按maven的三坐标来,那gradle是如何找到插件的呢?接下来我们就拆解一下gradle的寻插件之路。
gradle插件仓
gradle虽然不像maven有一个中央仓,但它专门为插件建了一个仓库:Gradle Plugin Portal,一个你可以用id找到插件的地方。
这里找插件非常方便,它会明确给出id和version,也会像maven中央仓一样给出示例代码。这里用id和version定位插件看上去很合理,正如上文所说,毕竟不是maven仓库,说不定gradle就新设计一套呢。但实际上并没有,这个仓库格式跟maven完全一样,后文会说明这一点。
maven中央仓
既然在Gradle Plugin Portal中用id和version定位插件看上去天经地义,那么我们就来看看我们有疑问的maven仓库吧,还是搜org.springframework.boot
搜出的第一名,我们一看就知道,它必然就是我们像找的对象。我们点进去,把构建工具选成gradle,它会给出这样的代码:implementation(platform("org.springframework.boot:org.springframework.boot.gradle.plugin:4.1.0-M4"))。我们把这条代码加到项目中,下载依赖,就会看到,这个项目只有一个pom文件,其中也只有一个依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-gradle-plugin</artifactId>
<version>4.1.0-M4</version>
</dependency>
毫无疑问,这就是我们要找的插件的本体。至此我们就搞清楚了gradle用id和version在maven仓库中定位插件的过程。总结一下,就是:
- id + version转化为:
"{id}:{id}.gradle.plugin:{version}",这就是经典的三段式maven坐标。 - 读取
"{id}:{id}.gradle.plugin:{version}"中的pom文件,这里面的依赖就是插件本体。这个pom只是一个“快捷方式”,也被称为Marker POM。
验证
我们拿io.spring.dependency-management验证一下。
完全印证了上述结论。
如何开发
Spring开发团队难道要为了搞个gradle插件,打两个包?如果真是这样,也太反人类了。事实上,gradle为开发插件提供了相应的插件,只要执行publish的task,就可以一炮双响。可以参考gradle关于发布插件的文档,以及id("org.springframework.boot")的源码。
Preparing to Publish Plugins
Publishing Plugins
spring-boot-gradle-plugin源码
Gradle Plugin Portal的真面目
前文提到Gradle Plugin Portal格式跟maven完全一样,如何能证明这一点呢?只需要进入任何一个插件的详情页,展开下部的see also,就会发现我们所言非虚。
为何如此设计
相信很多朋友了解了gradle这套设计之后,都会有个疑问,通过一个“快捷方式”转一下,多请求这一下,不是多此一举吗?实际上我认为这是gradle设计者的巧思,不但不是多此一举,并且很可能是设计者引以为豪的设计之一。它的好处我觉得有如下几点:
- 优雅,本身gradle用了Groovy和Kotlin就比xml优雅了几个数量级,id+version的DSL比三段式又更优雅。
- 复用,直接复用maven成熟的仓库,既免去设计仓库的工作,又不用从零开始构建生态。
- 区分,依赖的类库,gradle还是用三段式,一眼就能看出来跟maven的对应关系,因为不管是gradle还是maven,这些类库都是同一批,本质也都一样,而插件是构建工具,里面的代码是不能在项目代码里调的,与之对应的在maven的pom文件中,因为插件和依赖都是三段式,有时就会搞混。
- 解耦,一般情况下,id+version对应唯一的Marker POM,进一步对应唯一的jar包,但这个过程并不是不可改变的,gradle提供了干涉这个映射过程的API,但这其实只是理论上的情况,极少有人用。
更多推荐
所有评论(0)