maven dependency中scope=compile 和 provided区别

本文详细解析了Maven项目中pom.xml文件内的dependency标签中scope属性的作用,特别是provided与compile的区别。通过实例展示了不同scope设置如何影响项目的编译、测试及运行过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://supercharles888.blog.51cto.com/609344/981316

问题再现:

上次这边朋友问我一个问题,就是他们在pom.xml中的dependency中,看到有一些是<scope>provided</scope>的情况,比如如下:

  1. <dependency> 
  2.    <groupId>com.liferay.portal</groupId> 
  3.    <artifactId>portal-impl</artifactId> 
  4.    <version>6.1.0</version> 
  5.    <scope>provided</scope> 
  6. </dependency> 

他们问我scope在何种情况下要设置为provided,以及和scope设置为compile的区别。

 

解释:

其实这个问题很简单。

对于scope=compile的情况(默认scope),也就是说这个项目在编译,测试,运行阶段都需要这个artifact对应的jar包在classpath中。

而对于scope=provided的情况,则可以认为这个provided是目标容器已经provide这个artifact。换句话说,它只影响到编译,测试阶段。在编译测试阶段,我们需要这个artifact对应的jar包在classpath中,而在运行阶段,假定目标的容器(比如我们这里的liferay容器)已经提供了这个jar包,所以无需我们这个artifact对应的jar包了。

 

听起来很玄乎,对吧,其实一点也不难理解。举个scope=provided的例子。

比如说,假定我们自己的项目ProjectABC 中有一个类叫C1,而这个C1中会import这个portal-impl的artifact中的类B1,那么在编译阶段,我们肯定需要这个B1,否则C1通不过编译,因为我们的scope设置为provided了,所以编译阶段起作用,所以C1正确的通过了编译。测试阶段类似,故忽略。

那么最后我们要吧ProjectABC部署到Liferay服务器上了,这时候,我们到$liferay-tomcat-home\webapps\ROOT\WEB-INF\lib下发现,里面已经有了一个portal-impl.jar了,换句话说,容器已经提供了这个artifact对应的jar,所以,我们在运行阶段,这个C1类直接可以用容器提供的portal-impl.jar中的B1类,而不会出任何问题。

 

实际插件的行为:

刚才我们讲述的是理论部分,现在我们看下,实际插件在运行时候,是如何来区别对待scope=compile和scope=provided的情况的。

做一个实验就可以很容易发现,当我们用maven install生成最终的构件包ProjectABC.war后,在其下的WEB-INF/lib中,会包含我们被标注为scope=compile的构件的jar包,而不会包含我们被标注为scope=provided的构件的jar包。这也避免了此类构件当部署到目标容器后产生包依赖冲突。

<think>嗯,用户想了解Maven依赖中的scope用法相关场景。这个问题很具体,看来用户可能正在处理Java项目的依赖管理问题,需要明确不同scope的适用情况。从引用内容看,scopeMaven依赖管理的关键概念,决定了依赖在不同构建阶段的可用性。引用[1][2]都强调了scope对编译、测试、运行等生命周期阶段的影响。用户可能是中级开发者,因为初级开发者通常不会深究scope细节,而高级开发者可能更关注优化层面。需要系统性地解释scope的六种取值。引用[3][4][5]提供了重要补充信息,尤其是importsystem这两种较少见的scope。要特别注意避免常见的理解误区,比如:-providedruntime容易混淆-import不是真正的继承机制-system范围依赖的路径问题用户可能实际遇到了这些问题:依赖冲突、打包体积过大、测试环境异常等。在解释时要结合这些痛点,比如:-用provided避免ServletAPI冲突-用test优化生产包大小-用import管理多模块依赖还要注意技术细节的准确性:-compile是默认值,不声明scope时等效-runtime适用于数据库驱动等场景-system需要谨慎使用,可能破坏可移植性最后生成的提问要引导用户深入:传递性影响、版本冲突解决、现代替代方案等。这些延伸问题能帮助用户建立完整的依赖管理认知体系。</think>以下是Maven依赖中`<scope>`的详细说明及使用场景,结合引用内容整理: ### 一、Scope 核心作用 决定依赖在**构建生命周期不同阶段**的可用性,控制依赖的传递性,影响编译、测试、打包及运行行为[^2][^5]。 --- ### 二、六种 Scope 详解 #### 1. `compile`(**默认值**) - **作用阶段**:编译、测试、运行 - **传递性**:传递 - **场景**:核心依赖(如Spring Core、工具库)[^2][^5] ```xml <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.3.0</version> <!-- 默认 compile,可省略 --> </dependency> ``` #### 2. `provided` - **作用阶段**:编译、测试 - **传递性**:不传递 - **场景**:容器已提供的依赖(如Tomcat中的Servlet API)[^2][^5] ```xml <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> ``` #### 3. `runtime` - **作用阶段**:测试、运行 - **传递性**:传递 - **场景**:运行时必需但编译不需要(如JDBC驱动)[^2][^4] ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> <scope>runtime</scope> </dependency> ``` #### 4. `test` - **作用阶段**:测试 - **传递性**:不传递 - **场景**:单元测试依赖(如JUnit、Mockito)[^2][^5] ```xml <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> ``` #### 5. `system` - **作用阶段**:编译、测试 - **传递性**:不传递 - **场景**:使用本地系统路径的JAR(慎用,破坏可移植性)[^4] ```xml <dependency> <groupId>com.example</groupId> <artifactId>custom-lib</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${project.basedir}/lib/custom-lib.jar</systemPath> </dependency> ``` #### 6. `import` - **作用阶段**:仅依赖管理 - **传递性**:不传递 - **场景**:继承多个父POM的依赖管理(替代`<parent>`)[^3][^5] ```xml <dependency> <groupId>com.example</groupId> <artifactId>base-parent</artifactId> <version>1.0</version> <type>pom</type> <scope>import</scope> </dependency> ``` --- ### 三、关键使用场景 | **问题类型** | **推荐 Scope** | **优势** | |---------------------|----------------|-----------------------------------| | 避免容器依赖冲突 | `provided` | 排除重复依赖,减小包体积[^5] | | 优化生产包体积 | `test` | 移除测试专用依赖[^5] | | 模块化依赖管理 | `import` | 实现多继承,集中管理依赖[^3][^5] | | 运行时动态加载依赖 | `runtime` | 解耦编译与运行环境[^4] | --- ### 四、最佳实践 1. **优先使用默认作用域**:非必要不指定scope,保持简单性 2. **谨慎使用system**:破坏项目可移植性,优先部署到仓库 3. **传递性控制**:通过`<optional>true</optional>`或调整scope阻断依赖传递[^5] 4. **多模块项目**:用`import`整合多个依赖管理POM[^3] > 示例:通过`import`整合依赖管理[^3] > ```xml > <!-- 父模块 pom.xml --> > <dependencyManagement> > <dependencies> > <dependency> > <groupId>com.example</groupId> > <artifactId>shared-deps</artifactId> > <version>1.0</version> > <type>pom</type> > <scope>import</scope> > </dependency> > </dependencies> > </dependencyManagement> > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值