聊聊Maven的依赖传递、依赖管理、依赖作用域

这篇具有很好参考价值的文章主要介绍了聊聊Maven的依赖传递、依赖管理、依赖作用域。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 依赖传递

在Maven中,依赖是会传递的,假如在业务项目中引入了spring-boot-starter-web依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  	<version>2.7.4</version>
</dependency>

那么业务项目不仅直接引入了spring-boot-starter-web依赖,还间接引入了spring-boot-starter-web的依赖项:

spring-boot-starterspring-boot-starter-jsonspring-boot-starter-tomcatspring-webspring-webmvc

Maven依赖关系如下图所示:

外部库如下图所示:

其中,业务项目对spring-boot-starter-web的依赖称为直接依赖,对spring-boot-starter-web的依赖项:

spring-boot-starterspring-boot-starter-jsonspring-boot-starter-tomcatspring-webspring-webmvc

的依赖称为间接依赖。

2. 依赖管理

dependencyManagement元素主要用来统一管理依赖项的版本号。

假如父项目的pom文件中声明了如下依赖:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>
    </dependencies>
</dependencyManagement>    

那么子项目在添加该依赖时,可以不指定版本号:

<dependencies>
		<dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
    </dependency>
</dependencies>

Maven会自动找到父项目中声明的该依赖项的版本号,如下图所示:

这样的优点是可以统一在父项目中管理依赖项的版本号,如果需要升级版本,只需改动父项目一个地方即可,子项目不用改动。

说明:

1)dependencyManagement只是声明依赖项,并没引入依赖项,子项目仍需显式引入,不过可以不指定版本号

2)如果子项目不想使用继承的父项目中的版本号,在子项目中指定版本号即可

3. 依赖作用域

在Maven中,可以使用scope来指定当前依赖项的作用域,常见的值有:compile、provided、runtime、test、import等,如下所示:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>

3.1 compile

compile是默认的作用域,如果引入依赖时,没有明确指定作用域,则依赖作用域为compile。

作用域为compile的依赖,在编译、测试和运行时都是可用的,并且会参与项目的打包过程,该依赖会传递给依赖该模块的其他模块。

3.2 provided

作用域为provided的依赖,在编译和测试时是可用的,在运行时是不可用的,不会参与项目的打包过程,也不会传递给其他模块。

比如lombok依赖会在编译时生成相应的get、set等方法,在运行时就不需要这个依赖了,因此常常被指定为provided:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.16</version>
    <scope>provided</scope>
</dependency>

因为被指定为provided,项目打包时是不包含lombok依赖项的,如下图所示:

如果将上面的代码<scope>provided</scope>删除的话,运行时是下图这样的:

以上验证需将项目打包方式改为war,打包后查看WEB-INF/lib目录

3.3 runtime

作用域为runtime的依赖,在测试和运行时是可用的,在编译时是不可用的,会参与项目的打包过程,也会传递给依赖该模块的

其他模块。

说明:

作用域为runtime的依赖中的类,在项目代码里不能直接用,用了无法通过编译(这里指的是在src/main/java下使用)。

以mysql-connector-java为例,假如引入依赖时是下面这样的:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

下面的示例代码是可以编译通过的:

如果将作用域修改为runtime,上面的示例代码无法通过编译:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
    <scope>runtime</scope>
</dependency>

3.4 test

作用域为test的依赖,只在测试时可用(包括测试代码的编译、执行),不会参与项目的打包过程,也不会传递给其他模块。

常见的有junit、mockito等:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

因为被指定为test,项目打包时是不包含junit依赖项的,如下图所示:

如果将上面的代码<scope>test</scope>删除的话,运行时是下图这样的:

以上验证需将项目打包方式改为war,打包后查看WEB-INF/lib目录

说明:

作用域为test的依赖中的类或者注解只能在src/test/java下才可以使用,在src/main/java下无法使用,如junit包下的@Test注解和org.junit.Assert断言类。

3.5 import

每个项目,一般都会继承自一个父项目,在实际的工作中,这个父项目一般都是公司架构组提供的带有公司特色的一个基础项目,

当然也可以是spring boot官方的项目。

以spring boot官方的项目为例:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.4</version>
</parent>

这个父项目中,会使用dependencyManagement标签对依赖项的版本统一管理,子项目中,可以按需引入父项目

dependencyManagement中定义的依赖,但可以不指定版本号(版本号会自动继承父项目中定义的版本号)。

但是存在以下2个问题:

  1. Maven是单继承的,一个项目只能有一个parent项目
  2. parent项目dependencyManagement中的依赖项会越来越多,不好管理

依赖作用域import的出现就是为了解决以上问题,它可以通过非继承的方式批量引入另一个依赖项中

dependencyManagement元素中定义的依赖项,如下所示:

<dependencyManagement>
    <dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session-bom</artifactId>
      <version>${spring-session-bom.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

说明:<scope>import</scope>只能用在dependencyManagement下type为pom的dependency中。

以上代码等价于添加了以下6个依赖项:

可以看出,使用<scope>import</scope>可以模块化的管理依赖项,提高复用性,pom文件也更加简洁。

3.6 区别

综上所述,各个依赖作用域的区别如下表所示:

scope取值 编译时可用 测试时可用 运行时可用 是否参与打包 依赖传递
compile
provided × × ×
runtime ×
test × × × ×

4. 影响依赖传递的因素

4.1 依赖作用域(scope)

依赖作用域会影响依赖传递,从上表可以看出,如果scope为provided或者test,该依赖不会传递,只有scope为compile或者runtime,

该依赖才会传递。

4.2 可选依赖(optional)

通过dependency标签引入依赖时,可以通过<optional>指定该依赖是不是可选的,默认值为false:

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
	  <version>3.2.3</version>
    <optional>true</optional>
</dependency>

如果<optional>值为true,那么这个依赖不会传递。文章来源地址https://www.toymoban.com/news/detail-711684.html

到了这里,关于聊聊Maven的依赖传递、依赖管理、依赖作用域的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Maven 依赖传递和冲突、继承和聚合

    1.1.1 概念         假如有三个 Maven 项目 A 、 B 和 C ,其中项目 A  依赖 B ,项目 B  依赖 C 。那么我们可以说 A 依赖 C 。也就是说,依赖的关系为: A—B—C , 那么我们执行项目 A 时,会自动把 B 和 C 都下载导入到 A 项目的 jar 包文件夹中,这就是依赖的传递性。 1.1.2 作

    2024年01月21日
    浏览(47)
  • 【Maven教程】(四)坐标与依赖:坐标概念,依赖配置、范围、传递性和最佳实践 ~

    正如前面文章所述,Maven 的一大功能是管理项目依赖。为了能自动化地解析任何一个 Java 构件, Maven 就必须将它们唯一标识,这就依赖管理的底层基础——坐标。本节将详细分析 Maven 坐标的作用,解释其每一个元素;在此基础上,再介绍如何配置Maven, 以及相关的经验和技巧

    2024年02月09日
    浏览(48)
  • maven的scop作用域依赖问题导致idea社区版报错

    1. 错误:代码没改,卸了专业版后改用社区版出现以下报错 2024-01-08 16:34:29.374 ERROR [main] org.springframework.boot.SpringApplication.reportFailure:823 Application run failed java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration.propertySourc

    2024年02月02日
    浏览(33)
  • 解决maven 父工程依赖传递导致的 java.lang.NoClassDefFoundError: org/elasticsearch/xcontent/ToXContentObject

    因为项目需要,最近在学习elasticsearch,在使用elasticsearch Java 客户端时,出现了写问题,主要就是报各种的 NoClassDefFoundError 如: java.lang.NoClassDefFoundError: org/elasticsearch/xcontent/ToXContentObject ,出现这种 NoClassDefFoundError 的问题基本上就是maven 依赖错误或者版本不对,于是顺着这个

    2023年04月08日
    浏览(60)
  • 【Android Gradle 插件】Android 依赖管理 ④ ( 常用依赖配置分析 | implementation 依赖作用 | api 依赖作用 | compileOnly 依赖作用 )

    在本篇博客中逐一分析以下依赖配置 : implementation api compileOnly runtimeOnly annotationProcessor lintChecks lintPublish apk ( 已废弃 ) compile ( 已废弃 ) provided ( 已废弃 ) Android 依赖参考文档 : https://developer.android.google.cn/studio/build/dependencies compile 依赖作用: 编译打包 : 为 自己的项目模块 添加依

    2024年02月02日
    浏览(51)
  • maven-依赖管理-下

    依赖冲突 特殊优先 特殊优先∶当同级配置了相同资源的不同版本,后配置的覆盖先配置的(提醒:要尽量避免这种没有意义的冲突) 修改D:java_projectsmaven_Apom.xml, 引入mysql5.1 根据特殊优先原则: maven_A 生效的是mysql5.1.43 测试完后,注销到引入mysql5.1.43 , 这里是为了验证. 可选依

    2024年02月16日
    浏览(103)
  • 基于IDEA 进行Maven依赖管理

    Maven 依赖管理是 Maven 软件中最重要的功能之一。Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题,使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中,避免出现版本冲突和依赖缺失等问题。 我们通过定义 POM 文件,

    2024年01月23日
    浏览(51)
  • 基于 IDEA 进行 Maven 依赖管理

             Maven 依赖管理是 Maven 软件中最重要的功能之一。 Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题,使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中,避免出现版本冲突和依赖缺失等问题。        

    2024年01月19日
    浏览(52)
  • Maven高级-分模块开发&依赖管理

    目标 理解并实现分模块开发 (1)按照功能拆分 我们现在的项目都是在一个模块中,比如前面的SSM整合开发。虽然这样做功能也都实现了,但是也存在了一些问题,我们拿银行的项目为例来聊聊这个事。 网络没有那么发达的时候,我们需要到银行柜台或者取款机进行业务操作

    2023年04月09日
    浏览(39)
  • MAVEN利器:一文带你了解MAVEN中的依赖管理

    强大的构建工具——Maven。作为Java生态系统中的重要组成部分,Maven为开发人员提供了一种简单而高效的方式来构建、管理和发布Java项目。无论是小型项目还是大型企业级应用,Maven都能帮助开发人员轻松处理依赖管理、编译、测试和部署等任务。 在上一篇文章中,我们学习

    2024年02月10日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包