- 1. 依赖的传递性
- 1.1 概念
- 1.2 传递的原则
- 2. 依赖的排除
- 2.1 概念
- 2.2 配置方式
- 3. 版本仲裁
- 4. jar包冲突
- 4.1 jar包冲突原因
- 4.2 解决办法
- 4.2.1 IDEA的Maven Helper插件的使用
- 4.2.2 Maven的enforcer插件使用
- 4.3 用父工程做dependencyManagement统一管理依赖
A依赖B,B依赖C,那么A能不能直接使用C
1.2 传递的原则A依赖B,B依赖C,A能不能直接使用C,取决于B依赖C时使用的依赖范围scope
- B依赖C时使用compile:A能直接使用C
- B依赖C时使用test或provided范围,A不能直接使用C
当A依赖B,A又依赖C,但B和C依赖一个包的两个不同版本,这就可能发生版本冲突,需要使用依赖排序将其中一个排除掉
下面例子是iceberg-flink不引入slf4j-api的依赖传递
org.apache.iceberg
iceberg-flink
0.13.2
org.slf4j
slf4j-api
3. 版本仲裁
遵循以下原则: 1. 最短路径优先
在下面的例子中,对模块pro25-module-a来说,Maven会采用1.2.12版本
2. 路径相同时先声明者优先
在下面的例子中,在pro29-module-x中,先对pro30-module-y进行依赖声明,再对pro31-module-z进行依赖声明。所以Maven会采用1.2.17版本
主要体现为找不到类或找不到方法
- 抛异常:找不到类
此时抛出的常见的异常类型:
java.lang.ClassNotFoundException:编译过程中找不到类
java.lang.NoClassDefFoundError:运行过程中找不到类
java.lang.LinkageError:不同类加载器分别加载的多个类有相同的全限定名
原因:假如我们需要类A,在B-1.1.jar包中。但通过版本仲裁,采用了B-1.0.jar。而B-1.0.jar没有类A,就会抛找不到类A的异常
- 抛异常:找不到方法
程序找不到符合预期的方法。这种情况多见于通过反射调用方法,所以经常会导致:java.lang.NoSuchMethodError
- 没报错但结果不对
发生这种情况比较典型的原因是:两个jar包中的类分别实现了同一个接口,而这两个实现类恰巧是同一个名字。本来想使用第一个,确使用了第二个,虽然没报错,但由于实现细节不一样,导致结果不对
4.2 解决办法基本思路主要有两步:
- 把彼此冲突的jar包找到
- 在冲突的jar包中选定一个。具体可以通过exclusions排除依赖,或明确声明依赖
能够给我们罗列出来同一个jar包的不同版本,以及它们的来源。但是对不同jar包中同名的类没有办法
先安装Maven Helper插件 完整的pom.xml内容如下:
4.0.0
com.hh
maven-learn
0.1
org.apache.flink
flink-core
1.15.0
com.ververica
flink-connector-mysql-cdc
2.2.0
查看冲突的依赖如下
既可以检测同一个jar包的不同版本,又可以检测不同jar包中同名的类
添加maven-enforcer-plugin插件到pom.xml,并添加extra-enforcer-rules插件依赖,然后开启重复的类检测功能
完整的pom.xml内容如下:
4.0.0
com.hh
maven-learn
0.1
org.apache.flink
flink-core
1.15.0
com.ververica
flink-connector-mysql-cdc
2.2.0
org.apache.maven.plugins
maven-enforcer-plugin
3.0.0-M3
enforce-dependencies
validate
display-info
enforce
org.codehaus.mojo
extra-enforcer-rules
1.3
true
执行如下命令进行重复类检测
C:\Users\dell\Desktop\maven-learn>mvn clean enforcer:enforce
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------< com.hh:maven-learn >-------------------------
[INFO] Building maven-learn 0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-learn ---
[INFO]
[INFO] --- maven-enforcer-plugin:3.0.0-M3:enforce (default-cli) @ maven-learn ---
[INFO] Adding ignore: module-info
[INFO] Adding ignore: META-INF/versions/*/module-info
[WARNING] Could not find com.ververica:flink-connector-mysql-cdc:jar:2.2.0:compile at null
[WARNING] Could not find org.apache.flink:flink-core:jar:1.15.0:compile at null
[WARNING] Rule 0: org.apache.maven.plugins.enforcer.BanDuplicateClasses failed with message:
Duplicate classes found:
Found in:
javax.xml.bind:jaxb-api:jar:2.3.0:compile
jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
Duplicate classes:
javax/xml/bind/annotation/XmlValue.class
javax/xml/bind/ContextFinder.class
......省略部分......
javax/xml/bind/helpers/AbstractMarshallerImpl.class
Found in:
com.ververica:flink-connector-debezium:jar:2.2.0:compile
io.debezium:debezium-embedded:jar:1.5.4.Final:compile
Duplicate classes:
io/debezium/embedded/EmbeddedEngineChangeEvent.class
Found in:
javax.ws.rs:javax.ws.rs-api:jar:2.1.1:compile
jakarta.ws.rs:jakarta.ws.rs-api:jar:2.1.6:compile
Duplicate classes:
javax/ws/rs/ext/RuntimeDelegate$HeaderDelegate.class
javax/ws/rs/HEAD.class
......省略部分......
javax/ws/rs/client/CompletionStageRxInvoker.class
Found in:
jakarta.activation:jakarta.activation-api:jar:1.2.1:compile
javax.activation:activation:jar:1.1.1:compile
Duplicate classes:
javax/activation/DataContentHandlerFactory.class
javax/activation/SecuritySupport$2.class
......省略部分......
javax/activation/URLDataSource.class
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.215 s
[INFO] Finished at: 2022-07-01T16:06:35+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-enforcer-plugin:3.0.0-M3:enforce (default-cli) on project maven-learn: Some Enforcer rules
have failed. Look above for specific messages explaining why the rule failed. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
C:\Users\dell\Desktop\maven-learn>
这里虽然构建失败,但是不影响我们查看重复的类
4.3 用父工程做dependencyManagement统一管理依赖推荐一个公司或部门,用一个父工程做dependencyManagement,统一管理依赖关系,其它项目只需引用即可,避免每个人都去解决jar包冲突的问题。如果出现jar包冲突问题,只需修改该父工程的dependencyManagement就可以了