[maven 传递依赖问题请教]

2020-08-12 17:05:28 +08:00
 yema50

问题描述:

项目 A 里间接引入了 springboot-autoconfigure 依赖,autoconfigure 里 spring-data-elasticsearch 的版本是 3.1.5 并且<optional>true</optional>, 然后在该 A 项目里显式引入了 3.2.6 版本的 spring-data-elasticsearch ;

另一个项目 B 里引入了项目 A 并且也间接引入了 springboot-autoconfigure,此时在项目 B 里的 spring-data-elasticsearch 版本却是 3.1.5. 如果按照最近原则,不是应该优先选择 3.2.6 吗?请教大佬解答

2639 次点击
所在节点    Java
20 条回复
hejawy
2020-08-12 17:12:46 +08:00
idea 装个 maven helper 插件看下依赖的情况。另外显示指定版本不香吗,一定要纠结各种依赖导致的版本混乱?
yema50
2020-08-12 17:29:39 +08:00
@hejawy 嗯,装了 maven helper 插件,在项目 B 里查看 es 依赖来自于项目 A,并且版本是 3.1.5, 然后在项目 A 里查看确实是 3.2.6 。 目前是在 B 项目里显式指定了版本,但因为 A 其实是个公共模块, 所以希望能通过继承使用 A 里面的依赖
yema50
2020-08-12 17:30:26 +08:00
现在是真心想搞懂这个问题处在哪个地方
goldpumpkin
2020-08-12 17:51:10 +08:00
会不会是 B 项目引入其他包也有 es 3.1.5
yema50
2020-08-12 17:53:54 +08:00
@goldpumpkin 嗯,其它依赖里没有的,通过依赖树看过
bianjp
2020-08-12 19:21:21 +08:00
项目 B 的 POM 继承了 spring-boot-starter-parent 吧?

* spring-boot-starter-parent 继承了 spring-boot-dependencies
* spring-boot-dependencies 在其 dependencyManagement 中 import 了 spring-data-releasetrain
* spring-data-releasetrain 中定义了 spring-data-elasticsearch 的版本号

简单说来,就是项目 B 的 parent POM 的 dependencyManagement 中定义了 spring-data-elasticsearch 的版本号,这个定义优先级高于传递依赖中定义的版本。
yema50
2020-08-12 19:29:03 +08:00
@bianjp 感谢回复。 但是我也尝试过在项目 A 里写 dependencyManagement 来限定 es 的版本号,貌似不起作用
bianjp
2020-08-12 19:36:06 +08:00
@yema50 你需要在项目 B 的 dependencyManagement 中定义版本号。项目 A 作为项目 B 的一个普通依赖,其 dependencyManagement 优先级低于项目 B 的 parent POM 。
AlbertChen
2020-08-12 19:36:13 +08:00
Dependency mediation - this determines what version of an artifact will be chosen when multiple versions are encountered as dependencies. Maven picks the "nearest definition". That is, it uses the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, the first declaration wins.

"nearest definition" means that the version used will be the closest one to your project in the tree of dependencies. Consider this tree of dependencies:

A
├── B
│ └── C
│ └── D 2.0
└── E
└── D 1.0

In text, dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter.
AlbertChen
2020-08-12 19:38:58 +08:00
312ybj
2020-08-12 22:57:14 +08:00
springboot 和 es 的版本有限制, 你是不是在微信群里提过这个问题啊。3.2.*的 es 只能用 2.2.*的 springboot
qwerthhusn
2020-08-13 09:53:11 +08:00
Maven 的依赖确实搞不太懂,之前遇到过,一个 dependency 放在同一个 pom 的 dependencies 里面的上方和下方,最后出现的版本都不一样
yema50
2020-08-13 10:00:22 +08:00
@AlbertChen 感谢老哥回复。 看了 8 楼大佬的回复,我感觉是我理解错了。moduleB 里没有显示引入 es 依赖, 所以 es 依赖树会是 moduleB -> moduleA -> es 3.2.6. 因为 moduleB 里有间接引入 autoconfigure 的依赖,autoconfigure 里定义了 3.1.5 的 es 依赖但是设置了 optional 为 true, 所以其实这个 autoconfigure 里的依赖并不会传递到 moduleB 里吗?如果 autoconfigure 这个依赖传递进了 moduleB, 按照就近原则应该是 moduleB -> moduleA -> es326 路径更短
yema50
2020-08-13 10:02:04 +08:00
@312ybj 是的老哥, 我之前在微信群里问过。解决办法是在 moduleB 里显示引入了想要的版本, 但是对这个问题的原因有点没弄懂,所以又来问了一次 哈哈
yema50
2020-08-13 10:03:41 +08:00
@qwerthhusn 应该是如果有两个不同版本,并且路径深度一致, 会使用先找到的, 所以会出现根据定义的位置的先后 决定使用哪一个
yema50
2020-08-13 10:05:18 +08:00
@bianjp 感谢老哥解惑
bianjp
2020-08-13 12:46:21 +08:00
这个问题关键是 dependencyManagement, 不是路径深度。
yema50
2020-08-13 13:11:57 +08:00
@bianjp 嗯嗯,感觉这个是问题的 root cause 哈哈
Macolor21
2020-08-13 15:24:16 +08:00
可以尝试下 gradle,可以用 implemention 隐藏依赖细节,如果需要暴露对外依赖,可以用 api 。
yema50
2020-08-13 17:46:05 +08:00
@Macolor21 感觉是要学习学习 gradle 了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/697731

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX