Maven 直接依赖、间接依赖、依赖冲突、依赖仲裁


文章目录

  • 直接依赖和间接依赖
  • 依赖冲突
  • Maven 的依赖仲裁
    • 最短路径优先
    • 先声明优先
  • 手动解决依赖冲突

直接依赖和间接依赖


在项目中直接引入的依赖叫做直接依赖,而那些被动引入的就叫间接依赖

Maven 直接依赖、间接依赖、依赖冲突、依赖仲裁_第1张图片

比如上图中,A 是我们的项目,我们在项目中直接引入了 B 模块,所以 B 和 A 的关系就是直接依赖,而 B 工程内部引入了 C,
所以 B 和 C 也是直接依赖关系,如果 B 工程在引入 C 时,指定了 C 模块的依赖范围是 compile,那么 C 模
块就会随着 B 模块一同被引入到我们的工程A 中,这时候 A 和 C 的关系就是间接依赖


依赖冲突

Maven 的依赖冲突,我认为有两种情况,Maven 能自动解决的、需要手动解决的

1. Maven 可以自动解决的依赖冲突

在项目中,不管是直接依赖还是间接依赖,当有多个 相同, 不同的依赖引入时,
Maven 就会认为我们引入了相同模块的不同版本,其就会被判定为依赖冲突,这种情况 Maven 会用自己的仲裁机制帮
我们取舍


2. 需要手动解决的依赖冲突

模块间的 都不相同,但是引入的这些模块中具有相同路径的类(包名+类名
完全相同),这个时候就需要我们自己去解决依赖冲突问题


Maven 的依赖仲裁

依赖仲裁是 Maven 自动解决依赖冲突的手段,我们想更好的利用它,就必须知道其仲裁的规则,其通过 最短路径优先
先声明优先 两个依据来判断最终留下的模块


最短路径优先

当项目的依赖树中存在相同模块的不同版本时,Maven 的仲裁机制就会介入,其首先会通过最短路径的方式来对
冲突的模块进行取舍,如下图,假设我们的项目是A,明显C模块发生了依赖冲突,那么按照最短路径优先的原则,
Maven 最后会留下 A → B → C 1.0 这个路径下的 C 模块

Maven 直接依赖、间接依赖、依赖冲突、依赖仲裁_第2张图片

先声明优先

当两个依赖冲突的模块,其路径距离相同时,就会使用先声明优先的规则,这个就很简单了,就是留下先声明的模块,
如下图,假设我们的项目是A,两个冲突的模块C到 A 的距离是相同的,这时 Maven 就会根据先声明优先的规则选择
A → B → C 1.0 这个路径下的 C 模块,因为其声明在前

Maven 直接依赖、间接依赖、依赖冲突、依赖仲裁_第3张图片

至于什么叫先声明,非常简单,用上图例子,我写个伪代码


<dependency>
    <groupId>BgroupId>
    <artifactId>BartifactId>
    <version>releaseversion>
dependency>
<dependency>
    <groupId>DgroupId>
    <artifactId>DartifactId>
    <version>releaseversion>
dependency>

了解仲裁规则后,也可以利用 Maven 的仲裁规则,保留自己想要的模块,比如上面例子中,我们想保留模块 C 2.0,
那么就可以将模块 C 2.0 的依赖信息主动声明在依赖列表的最前面,这样不论是最短路径规则还是先声明的规则,都会
判定 C 2.0 被保留,伪代码如下:


<dependency>
    <groupId>CgroupId>
    <artifactId>CartifactId>
    <version>2.0version>
dependency>
<dependency>
    <groupId>BgroupId>
    <artifactId>BartifactId>
    <version>releaseversion>
dependency>
<dependency>
    <groupId>DgroupId>
    <artifactId>DartifactId>
    <version>releaseversion>
dependency>

手动解决依赖冲突


需要手动解决的情况,是指不同模块中,具有相同路径的类(包名和类名完全相同),从而导致项目启动后,类加载器加载了
同名的非目标类,从而出现 ClassNotFoundExceptionNoClassDefFoundErrorLinkageError 等类似的错误

手动解决依赖冲突,首先需要找出路径相同的类所在的模块,其次决定要留用的模块

找出类路径相同的模块

可以借助 Maven 的生命周期插件 maven-enforcer-plugin

1. 在项目的 Pom.xml 中添加配置

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.pluginsgroupId>
            <artifactId>maven-enforcer-pluginartifactId>
            <version>1.4.1version>
            <executions>
                <execution>
                    <id>enforce-dependenciesid>
                    <phase>validatephase>
                    <goals>
                        <goal>display-infogoal>
                        <goal>enforcegoal>
                    goals>
                execution>
            executions>
            <dependencies>
                <dependency>
                    <groupId>org.codehaus.mojogroupId>
                    <artifactId>extra-enforcer-rulesartifactId>
                    <version>1.0-beta-4version>
                dependency>
            dependencies>
            <configuration>
                <rules>
                    <banDuplicateClasses>
                        <findAllDuplicates>truefindAllDuplicates>
                    banDuplicateClasses>
                rules>
            configuration>
        plugin>
    plugins>
build>

(2) 执行 mvn clean package enforcer:enforce 命令后,就能看见重复的类和模块

Maven 直接依赖、间接依赖、依赖冲突、依赖仲裁_第4张图片

(3) 找到冲突的模块后,删掉弃用的模块,如果是直接依赖的模块直接删除依赖信息就好,
如果是间接依赖的模块,就要使用 排除依赖传递,方式如下:

<dependency>
    <groupId>groupId>
    <artifactId>artifactId>
    <version>version>
    
    <exclusions>
        <exclusion>
            <groupId>要弃用的模块的groupIdgroupId>
            <artifactId>要弃用的模块的artifactIdartifactId>
        exclusion>
    exclusions>
dependency>

你可能感兴趣的:(#,Maven,maven)