Maven依赖作用域和依赖传递的使用
作者:守望时空33 发布时间:2022-07-24 19:08:33
在Java项目开发中,Maven是我们最常用的依赖管理和构建工具了!我们常常通过添加dependency
节点,就能够很方便地加入依赖,而不需要我们自己去手动下载jar
文件并引入。
今天主要是来总结一下在Maven中依赖的作用域和传递。
1,依赖作用域
通过在每个dependency
中设定scope
字段,即可声明其作用域,例如:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<!-- 声明作用域 -->
<scope>provided</scope>
</dependency>
上面我们就设定了lombok
这个依赖的作用域为provided
。
常用的作用域字段值及其意义如下:
compile
这是默认的scope
(即你不写scope
字段的话,这个依赖作用域就是compile
),表示依赖在编译、测试和运行时都是可用的,并且会参与项目的打包过程,该依赖会传递给依赖该模块的其他模块provided
表示依赖在编译和测试时是可用的,但该依赖不会参与程序运行阶段,即程序运行时无法调用该依赖中的类,它不会参与项目的打包过程,也不会传递给其他模块runtime
表示依赖仅在运行时是可用的,但在编译和测试时不需要,它会传递给依赖该模块的其他模块,但不会参与项目的打包过程test
表示依赖只在测试和运行时使用,不会参与项目的打包过程,也不会传递给其他模块
可见一个Maven项目,从编译到运行会经历三个阶段:编译 → 测试 → 运行
不同作用域在三个阶段的可见性如下表:
编译时可用 | 测试时可用 | 运行时可用 | |
---|---|---|---|
compile | √ | √ | √ |
provided | √ | √ | x |
runtime | x | √ | √ |
test | x | √ | x |
2,作用域和打包
我们常常会使用maven-assembly-plugin
插件,让我们在打包的时候将所有的依赖都打包至最后的jar
文件中,使得jar
文件可以直接运行。
不过真的是所有的依赖都会被打包到最后的jar
中吗?
其实并不是,在使用maven-assembly-plugin
插件插件时,默认只有scope
为compile
和runtime
的依赖才会被包含在最终的结果中。
因此,为了减小最终jar
的大小,我们应当将运行时不需要的依赖设置为provided
或者test
,当然这也是根据用途选择。
例如lombok
依赖会在编译的时候生成getter
和setter
的代码,但是运行的时候这个依赖就不需要了,因此它常常被设定为provided
。
但是在Spring Boot开发中就不一样了,Spring Boot工程中,使用的是spring-boot-maven-plugin
,这个插件也能完成同样的目的,即打包时将所有的依赖全部打包到一个jar
中,但是这个插件会将所有的依赖都打包进去,无论其scope
是什么。
不过,我们可以在这个插件中进行配置,声明打包时需要排除的依赖,例如:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<!-- 打包时排除lombok依赖 -->
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
3,依赖的传递
事实上,在Maven中,依赖也是会传递的,我们先创建一个名为first
的项目,并引入lombok
依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.gitee.swsk33</groupId>
<artifactId>first</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
</dependencies>
</project>
这是项目first
的pom.xml
文件,其groupId
为com.gitee.swsk33
,其artifactId
为first
,其版本为1.0.0
,现在在其工程目录下执行mvn clean install
安装至本地仓库使得待会可以引用它。
现在在新建项目second
,并引用上述的first
作为依赖,如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.gitee.swsk33</groupId>
<artifactId>second</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引用first项目 -->
<dependency>
<groupId>com.gitee.swsk33</groupId>
<artifactId>first</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
好的,现在展开IDEA左侧栏的外部库部分,看看second
项目的依赖:
可见second
项目仅仅是引入了first
项目,但为什么外部库中包含了lombok
依赖呢?这是因为first
依赖lombok
,而second
依赖first
时,lombok
也被传递给了second
。
同样地,如果现在又有一个项目third
依赖second
呢?那么third
也会间接依赖lombok
,也可以使用lombok
中的类。
当然,依赖并不总是会传递的,有下列因素会影响依赖传递。
(1) scope
作用域
scope
不仅仅代表这个依赖的作用域,也会影响依赖的传递,只有scope
为compile
和runtime
的依赖是会传递的。
假设现在把上述first
项目中的lombok
依赖scope
改成provided
或者test
,然后重新执行mvn clean install
,你就会发现在second
的依赖中,就看不到lombok
了!
(2) optional
字段
除了scope
之外,还可以设定依赖的optional
字段,当设定为true
时代表这个依赖是可选的,那么这时无论其scope
是什么,这个依赖都不会传递。默认情况下,即不声明依赖的optional
字段时,它的值是false
。
现在将first
中的lombok
依赖的optional
字段声明为true
:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<optional>true</optional>
</dependency>
然后重新mvn clean install
,再次打开second
项目,你就会发现lombok
依赖就没有传递过来了!
所以如果在制作外部库需要其他人引用的时候,我们可以将一些仅仅是外部库需要使用但是其它项目不一定要使用的依赖的optional
设定为true
,避免其他开发者引入你的外部库时发生依赖冲突。
来源:https://juejin.cn/post/7239585610858823739


猜你喜欢
- import java.io.BufferedReader;import java.io.InputStreamReader;import
- Android Intent调用 Uri的方法总结//调用浏览器Uri uri = Uri.parse(""); Int
- 1:新建一个项目运行起来,可以看到顶部一直有个标题栏看着不是很美观2:有两种方法可以去除顶部标题栏(1)将代码中AndroidManifes
- android中提供了4中动画: AlphaAnimation 透明度动画效果 ScaleAnimation 缩放动画效果 Translat
- 本文实例为大家分享了Android用户注册界面的设计,供大家参考,具体内容如下I. 实例目标 设计一个用户注册界面,在其中要使用到一些基础控
- QTableWidget 是 Qt 中的表格组件类。在窗体上放置一个 QTableWidget 组件后,可以在 Property Edito
- 第一步:下载需要添加的jar包可以在maven库中查找下载,也可以在对应官网下载maven库网址:https://mvnrepository
- 具体详细介绍请看下文:在使用文件进行交互数据的应用来说,使用FTP服务器是一个很好的选择。本文使用Apache Jakarta Common
- 本文最终结果大概是这样的,使用java技术随机生成10个数,然后填充一个数组并在消息框中显示数组内容,接着对数组求和输出,将结果显示在消息框
- springmvc @RequestBody String类型参数通过如下配置: <bean id="mapp
- 建造者模式针对的是复杂对象的构建,比如一个产品有多个部分构成,每个部分都可以单独进行生产,这时候就可以用建造者模式,由Builder构造产品
- 本文实例讲述了C#端口转发用法。分享给大家供大家参考。具体分析如下:这里以链接3389的时候为例例子1:连接a机器的3389端口连不上,因为
- 本文实例为大家分享了Android TextView实现跑马灯效果的具体代码,供大家参考,具体内容如下当Layout中只有一个TextVie
- 前台form 表单:设置method=post,enctype=multipart/form-data。struts2在原有的上传解析器继承
- Android启动的四种方式分别为standard,singleTop,singleTask,singleInstence。standard
- Java数组初始化需要指定数组容量,但是在许多情况下需要动态扩充容量。有两种方法可以实现:1.采用ArrayList类数组,它可以在需要时自
- 1. 出故障了没办法,干it这一行,就得天天面对故障,大家就是传说中的消防员,到处救火。不过,这次的故障范围有点大,宿主机都打不开了。好在监
- 我们经常会使用springboot创建web应用,在springboot中金静态资源是如何存放的呢?静态资源映射规则我们先创建一个sprin
- 特性一:委托委托是C#语言 * 有的概念,相当于C/C++中的函数指针,与C/C++中函数指针的不同之处是:委托是面向对象的、类型安全的和保险
- Swagger是一款遵循 Restful 风格的接口文档开发神器,支持基于 API 自动生成接口文档,接口文档始终与 API 保持同步,不再