会得到groupID是项目名,artifactId是module名,version是未知的一个依赖项。假如我将A编译为静态包并发布到仓库,并运用了pom中的依赖描述,一定会得到无法找到:Demo-B-unspecified.pom 的问题。
当然,这个问题可以通过在APP中重新声明 B的依赖 来解决。
这意味着,我们需要时刻保持警惕,维护各个module的依赖。否则,我们无法同时享受:静态包减少编译 & 随心的修改局部并集成测试
这显然是一件不人道主义的事情。
反思一下,对于A而言,它需要B,但仅在两个时机需要:
-
编译时受检,完成编译
-
运行时
作为一个library,它本身并不对应运行时,所以,compileOnly 是其声明对B的依赖的最佳方式。这意味着,最终对应运行时 的内容,即APP,需要在编译时加入 对B的依赖。在原先 A使用Api方式声明对B的依赖时,是通过gradle分析pom文件实现的依赖加入。而现在,需要人为维护,只需要实现 人道主义,就可以鱼和熊掌兼得。
=====================================================================
一般我们会像下面的演示代码一样声明依赖:
//APP:
implementation project(‘A’)
implementation project(‘Foo’)
//A:
implementation project(‘B’)
implementation project(‘Bar’)
因为依赖传递性,APP其实依赖了A,Foo,B,Bar。其实就是一颗树中,除去根节点的节点集合。而对于一个非根节点,它被依赖的形式只有两种:
-
静态包,不需要重新编译,节约编译时间
-
module,需要再次编译,可以运用最新改动
我们可以定义这样一个键值对信息:
project.ext.depRules = [
“B”: “p”,
“A”: “a”
]
"p"代表使用project,"a"代表使用静态包。
并将这颗树的内容表达出来:我们先忽略掉Foo和Bar
project.ext.deps = [
“A” : [
“B”: [
“p”: project(‘:B’),
“a”: ‘leobert:B:1.0.0’
]
],
“APP”: [
“A”: [
“p”: project(‘:A’),
“a”: ‘leobert:A:1.0.0’
]
]
].with(true) {
A.each { e ->
APP.put(e.key, e.value)
}
}
以A为例,我们可以通过代码实现动态添加依赖:
project.afterEvaluate { p ->
println(“handle deps for:” + p)
deps.A.each { e ->
def rule = depRules.get(e.key)
println(“find deps of A: rule is” + rule + " ,dep is:" + e.value.get(rule).toString())
project.dependencies.add(“compileOnly”, e.value.get(rule))
}
}
同理,对于APP:
project.afterEvaluate { p->
println(“handle deps for:” + p)
deps.APP.each { e ->
def rule = depRules.get(e.key)
println(“find deps of App:rule is” + rule + " ,dep is:" + e.value.get(rule)