前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2. 依赖管理

2. 依赖管理

作者头像
捞月亮的小北
发布2023-12-01 10:43:13
1670
发布2023-12-01 10:43:13
举报
文章被收录于专栏:捞月亮的小北

我们现在已经能把项目拆分成一个个独立的模块,当在其他项目中想要使用独立出来的这些模块,只需要在其 pom.xml 使用标签来进行 jar 包的引入即可。

其实就是依赖,关于依赖管理里面都涉及哪些内容,我们就一个个来学习下:

  • 依赖传递
  • 可选依赖
  • 排除依赖

我们先来说说什么是依赖:

依赖指当前项目运行所需的 jar,一个项目可以设置多个依赖。

格式为:

代码语言:javascript
复制
<!--设置当前项目所依赖的所有jar-->
<dependencies>
    <!--设置具体的依赖-->
    <dependency>
        <!--依赖所属群组id-->
        <groupId>org.springframework</groupId>
        <!--依赖所属项目id-->
        <artifactId>spring-webmvc</artifactId>
        <!--依赖版本号-->
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>


<p data-line="247" class="sync-line" style="margin:0;"></p>

1. 依赖传递与冲突问题

在项目所依赖的这些 jar 包中,有一个比较大的区别就是有的依赖前面有箭头>,有的依赖前面没有。

那么这个箭头所代表的含义是什么?

打开前面的箭头,你会发现这个 jar 包下面还包含有其他的 jar 包

你会发现有两个maven_03_pojo​ 的依赖被加载到 Dependencies 中,那么maven_04_dao​ 中的maven_03_pojo​ 能不能使用呢?

要想验证非常简单,只需要把maven_02_ssm​ 项目中 pom.xml 关于maven_03_pojo​ 的依赖注释或删除掉

在 Dependencies 中移除自己所添加maven_03_pojo​ 依赖后,打开 BookServiceImpl 的类,你会发现 Book 类依然存在,可以被正常使用

这个特性其实就是我们要讲解的依赖传递。

依赖是具有传递性的:

说明:A 代表自己的项目;B,C,D,E,F,G 代表的是项目所依赖的 jar 包;D1 和 D2 E1 和 E2 代表是相同 jar 包的不同版本

(1) A 依赖了 B 和 C,B 和 C 有分别依赖了其他 jar 包,所以在 A 项目中就可以使用上面所有 jar 包,这就是所说的依赖传递

(2) 依赖传递有直接依赖和间接依赖

  • 相对于 A 来说,A 直接依赖 B 和 C,间接依赖了 D1,E1,G,F,D2 和 E2
  • 相对于 B 来说,B 直接依赖了 D1 和 E1,间接依赖了 G
  • 直接依赖和间接依赖是一个相对的概念

(3)因为有依赖传递的存在,就会导致 jar 包在依赖的过程中出现冲突问题,具体什么是冲突?Maven 是如何解决冲突的?

这里所说的依赖冲突是指项目依赖的某一个 jar 包,有多个不同的版本,因而造成类包版本冲突。

情况一: 在maven_02_ssm​ 的 pom.xml 中添加两个不同版本的 Junit 依赖:

代码语言:javascript
复制
   <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
</dependencies>


<p data-line="311" class="sync-line" style="margin:0;"></p>

通过对比,会发现一个结论

  • 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的。

情况二: 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高

  • A 通过 B 间接依赖到 E1
  • A 通过 C 间接依赖到 E2
  • A 就会间接依赖到 E1 和 E2,Maven 会按照层级来选择,E1 是 2 度,E2 是 3 度,所以最终会选择 E1

情况三: 声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的

  • A 通过 B 间接依赖到 D1
  • A 通过 C 间接依赖到 D2
  • D1 和 D2 都是两度,这个时候就不能按照层级来选择,需要按照声明来,谁先声明用谁,也就是说 B 在 C 之前声明,这个时候使用的是 D1,反之则为 D2

但是对应上面这些结果,大家不需要刻意去记它。因为不管 Maven 怎么选,最终的结果都会在 Maven 的Dependencies​ 面板中展示出来,展示的是哪个版本,也就是说它选择的就是哪个版本,如:

如果想更全面的查看 Maven 中各个坐标的依赖关系,可以点击 Maven 面板中的show Dependencies

​​​

​​​

在这个视图中就能很明显的展示出 jar 包之间的相互依赖关系。

2. 可选依赖和排除依赖

依赖传递介绍完以后,我们来思考一个问题,

  • maven_02_ssm 依赖了 maven_04_dao
  • maven_04_dao 依赖了 maven_03_pojo
  • 因为现在有依赖传递,所以 maven_02_ssm 能够使用到 maven_03_pojo 的内容
  • 如果说现在不想让 maven_02_ssm 依赖到 maven_03_pojo,有哪些解决方案?

说明:在真实使用的过程中,maven_02_ssm 中是需要用到 maven_03_pojo 的,我们这里只是用这个例子描述我们的需求。因为有时候,maven_04_dao 出于某些因素的考虑,就是不想让别人使用自己所依赖的 maven_03_pojo。

方案一:可选依赖

  • 可选依赖指对外隐藏当前所依赖的资源---不透明

maven_04_dao​ 的 pom.xml,在引入maven_03_pojo​ 的时候,添加optional

代码语言:javascript
复制
<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>maven_03_pojo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--可选依赖是隐藏当前工程所依赖的资源,隐藏后对应资源将不具有依赖传递-->
    <optional>true</optional>
</dependency>


<p data-line="368" class="sync-line" style="margin:0;"></p>

此时 BookServiceImpl 就已经报错了,说明由于 maven_04_dao 将 maven_03_pojo 设置成可选依赖,导致 maven_02_ssm 无法引用到 maven_03_pojo 中的内容,导致 Book 类找不到。

方案二:排除依赖

  • 排除依赖指主动断开依赖的资源,被排除的资源无需指定版本---不需要

前面我们已经通过可选依赖实现了阻断 maven_03_pojo 的依赖传递,对于排除依赖,则指的是已经有依赖的事实,也就是说 maven_02_ssm 项目中已经通过依赖传递用到了 maven_03_pojo,此时我们需要做的是将其进行排除,所以接下来需要修改 maven_02_ssm 的 pom.xml

代码语言:javascript
复制
<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>maven_04_dao</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--排除依赖是隐藏当前资源对应的依赖关系-->
    <exclusions>
        <exclusion>
            <groupId>com.itheima</groupId>
            <artifactId>maven_03_pojo</artifactId>
        </exclusion>
    </exclusions>
</dependency>


<p data-line="393" class="sync-line" style="margin:0;"></p>

这样操作后,BookServiceImpl 中的 Book 类一样也会报错。

当然exclusions​ 标签带s​ 说明我们是可以依次排除多个依赖到的 jar 包,比如 maven_04_dao 中有依赖 junit 和 mybatis,我们也可以一并将其排除。

代码语言:javascript
复制
<dependency>
    <groupId>com.itheima</groupId>
    <artifactId>maven_04_dao</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--排除依赖是隐藏当前资源对应的依赖关系-->
    <exclusions>
        <exclusion>
            <groupId>com.itheima</groupId>
            <artifactId>maven_03_pojo</artifactId>
        </exclusion>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </exclusion>
    </exclusions>
</dependency>


<p data-line="420" class="sync-line" style="margin:0;"></p>

介绍我这两种方式后,简单来梳理下,就是

  • A依赖B,B依赖C​,C​ 通过依赖传递会被A​ 使用到,现在要想办法让A​ 不去依赖C
  • 可选依赖是在 B 上设置<optional>​,A​ 不知道有C​ 的存在,
  • 排除依赖是在 A 上设置<exclusions>​,A​ 知道有C​ 的存在,主动将其排除掉。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 依赖传递与冲突问题
  • 2. 可选依赖和排除依赖
    • 方案一:可选依赖
      • 方案二:排除依赖
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档