目录
1. 依赖的传递性
1.1 概念
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
2. 依赖的排除
2.1 概念
当A依赖B,A又依赖C,但B和C依赖一个包的两个不同版本,这就可能发生版本冲突,需要使用依赖排序将其中一个排除掉
2.2 配置方式
下面例子是iceberg-flink不引入slf4j-api的依赖传递
<dependency>
<groupId>org.apache.iceberg</groupId>
<artifactId>iceberg-flink</artifactId>
<version>0.13.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
3. 版本仲裁
遵循以下原则:
1. 最短路径优先
在下面的例子中,对模块pro25-module-a来说,Maven会采用1.2.12版本
2. 路径相同时先声明者优先
在下面的例子中,在pro29-module-x中,先对pro30-module-y进行依赖声明,再对pro31-module-z进行依赖声明。所以Maven会采用1.2.17版本
4. jar包冲突
4.1 jar包冲突原因
主要体现为找不到类或找不到方法
- 抛异常:找不到类
此时抛出的常见的异常类型:
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排除依赖,或明确声明依赖
4.2.1 IDEA的Maven Helper插件的使用
能够给我们罗列出来同一个jar包的不同版本,以及它们的来源。但是对不同jar包中同名的类没有办法
先安装Maven Helper插件
完整的pom.xml内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hh</groupId>
<artifactId>maven-learn</artifactId>
<version>0.1</version>
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-core</artifactId>
<version>1.15.0</version>
</dependency>
<dependency>
<groupId>com.ververica</groupId>
<artifactId>flink-connector-mysql-cdc</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</project>
查看冲突的依赖如下
4.2.2 Maven的enforcer插件使用
既可以检测同一个jar包的不同版本,又可以检测不同jar包中同名的类
添加maven-enforcer-plugin插件到pom.xml,并添加extra-enforcer-rules插件依赖,然后开启重复的类检测功能
完整的pom.xml内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hh</groupId>
<artifactId>maven-learn</artifactId>
<version>0.1</version>
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-core</artifactId>
<version>1.15.0</version>
</dependency>
<dependency>
<groupId>com.ververica</groupId>
<artifactId>flink-connector-mysql-cdc</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<id>enforce-dependencies</id>
<phase>validate</phase>
<goals>
<goal>display-info</goal>
<goal>enforce</goal>
</goals>
</execution>
</executions>
<dependencies>
<!-- 官网地址:http://www.mojohaus.org/extra-enforcer-rules/index.html -->
<!-- 1.3版本和maven-enforcer-plugin的3.0.0、3.1.0两个版本不兼容 -->
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
<configuration>
<rules>
<!-- banDuplicateClasses由extra-enforcer-rules提供 -->
<banDuplicateClasses>
<findAllDuplicates>true</findAllDuplicates>
</banDuplicateClasses>
</rules>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
执行如下命令进行重复类检测
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就可以了