maven 的子模块依赖规则无法传导到父模块?

1 天前
 abcbuzhiming
最近实践中遇到了依赖冲突,在解决中无意中发现了下面这样奇怪的现象。

问题一,项目主要靠 spring 启动,项目有两个模块,刚开始的时候,二者的 pom.xml 文件设置如下
moudle-A
|--moudle-B


moudle-B
|--lib1

moudle-A 已经在依赖中添加了 moudle-B 。
moudle-B 依赖 lib1 ,且 moudle 某个 service 在被 spring 初始化的时候,有一个 @PostConstruct 操作,这个操作会调用 lib1 中的类。

问题现象,程序的启动入口在 moudle-A 中,一旦启动,就报在初始化那个 service 时找不到 lib1 中的类,项目跑不起来。解决办法很简单,把 moudle-A 的依赖改一下,改成下面这样:
moudle-A
|--moudle-B
|--lib1

就可以了。
我的疑惑是 moudle-B 依赖 lib1 的这点无法传导给 moudle-A 吗? maven 的依赖规则是严格的按照 pom.xml 文件为单位隔离的吗?



问题二:还是两个模块
moudle-A
|--moudle-B


moudle-B
|--lib1
----|--lib3 v1 (隐式依赖)
|--lib2
|--lib3 v2

moudle-B 的 pom.xml 显式的依赖 lib1 ,lib2 ,lib3 v2 。
lib2 拆包分析,自身没有定义依赖,但是需要 lib3 v2 才能运行起来。
但是 lib1 自身依赖一个 lib3 v1 版本,于是就和 lib3 v2 冲突了。于是我只能编辑 moudle-B 的 pom.xml ,在 lib1 的依赖下显式的把 lib3 v1 给排除掉,像下面这样
<dependency>
<groupId>com.xxx</groupId>
<artifactId>lib1</artifactId>
<exclusions>
<exclusion>
<artifactId>lib3</artifactId>
<groupId>com.yyy</groupId>
</exclusion>
</exclusions>
</dependency>

结果程序跑不起来,检查发现程序仍然在使用在使用 lib3 v1 版本,导致 lib2 无法启动,排除无效。后来用 maven 分析了一下,发现问题居然出现在 moudle-A ,moudle-A 引用 moudle-B 的时候,居然还是认为需要依赖 lib3 v1 。最后我没办法,我在 moudle-A 引用 moudle-B 的地方,把 lib3 排除掉了,然后自己加个新的 lib3.就像下面这样
<dependency>
<groupId>com.xxx</groupId>
<artifactId>module-B</artifactId>
<exclusions>
<exclusion>
<artifactId>lib3</artifactId>
<groupId>com.yyy</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.yyy</groupId>
<artifactId>lib3</artifactId>
<version>v2</version>
</dependency>

问题是解决了,但是这个方法真的是最佳方法吗?而且问题还是和第一个一样,maven 的父模块,是不检查子模块 pom.xml 文件内容的吗?子模块对依赖的一些定义设置,无法传导到父模块?
641 次点击
所在节点    Java
6 条回复
wxw752
23 小时 24 分钟前
1. 你那个 module-B 在引入 lib1 的时候,scope 怎么写的? 是不是写了<scope>provided</scope>

2. 两种可能,maven clean 一下试试,怀疑是 module-a 引用了 module-b 的缓存。第二种可能,module-a 里面除了 module-b 引用过 lib3 v1 ,还有其他包也依赖 lib3 v1 ,maven 依赖树中找到的最近版本是 v1 。
不过可以肯定的是,那么写绝对不正常
miaotaizi
22 小时 2 分钟前
你要不把你的 pom.xml 复制给 ai 让 ai 帮你看看?

按照你标题的描述我觉得能起作用才怪了。子模块里面的依赖为什么父模块要知道? 反过来, 父模块的依赖一定是能被子模块使用。
PolarisY
17 小时 7 分钟前
给你介绍个命令 mvn dependency:tree -Dverbose ,用用看你能发现什么。
shangfabao
6 小时 5 分钟前
你把
moudle-B 的引用贴出来
helloworld19
5 小时 53 分钟前
👀
abcbuzhiming
1 小时 27 分钟前
@wxw752
1.没有写过这个 scope
2.后面发现。还真是这个原因。


@miaotaizi
按照 maven 官方文档的说法,子模块的依赖是会传导进父模块的,所以父模块肯定知道子模块的依赖


@PolarisY
感谢你的这个命令,我是思维定式了,被困在 IDEA 这个 IDE 里提供的 maven help 提供的信息中。正是这个命令,让我发现了一件有趣的事情:
+- (com.squareup.okhttp3:okhttp:jar:3.14.9:compile - version managed from 3.12.13; omitted for duplicate)
明明,lib1 依赖的 okhttp 是 3.12.13 ,但是运行 mvn dependency:tree 后,显示 compile 时的依赖却是 3.14.9 。很显然,我原本以为这个依赖是 lib1 造成的,现在看 lib1 虽然要引用依 okhttp ,但是版本却不是它指定的。
最后我顺藤摸瓜的找到了一个命令
mvn help:effective-pom -Dverbose
这个命令指出,module A 引用的另外一个 lib ,这个 lib 中,指定了 okhttp:jar:3.14.9 ,根据 maven 依赖冲突调解路径最近原则,maven 实际用了这个版本。

所以,module B 不需要排除依赖,直接在 module A 中强制指定 okhttp 为 4.x ,根据路径最近原则,这个版本会强行覆盖 module B 中的 okhttp 依赖,于是问题终于解决了

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

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

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

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

© 2021 V2EX