《Maven官方指南》可选的依赖和依赖排除

简介:

简介

这节主要讨论了可选的依赖排除功能。这将帮助用户理解它们是什么,怎么使用它们,它们是怎么工作的,和使用它们的最好的方式。同样也解释了为什么排除是在每个依赖的基础上,而不是在POM级别。

可选的依赖

当不可能把一个项目分裂成子模块(不管什么原因)的时候,我们可以使用可选的依赖。它的思想就是:在项目中一些依赖仅仅被某些功能使用,并且如果这个功能不被使用,这个依赖就不需要。理想情况下,根据核心的功能性项目,一个功能被分成子模块… 如果你决定使用子模块的功能,因为你必须需要他们的全部,所以新的子项目仅仅有不可选的依赖。

然而,因为这个项目不可能被分成子模块,所以这些依赖被声明成可选的。如果一个用户想要使用和一个可选的依赖相关的功能,他们将不得不在他们自己的项目中重新声明可选的依赖。用这种方法处理这种情况不是的最好的方式,但是可选的依赖和依赖排除也是一个权宜的解决办法。

为什么使用可选的依赖?

声明可选的依赖,重点不是为了节省空间/内存,因为这些jar最后可能被打进一个WAR、EAR、EJB等,重点是当一个用户为了使用一个项目时来控制实际的依赖列表。包含了一个错误的jar可能会违反一个许可协议,引起环境变量问题等。

怎么使用可选的标签?

在你的依赖声明中,通过简单的设置<optional> 标签为true,一个依赖就被声明为可选的。一个简单的示例:

01 <project>
02   ...
03   <dependencies>
04     <!-- declare the dependency to be set as optional -->
05     <dependency>
06       <groupId>sample.ProjectA</groupId>
07       <artifactId>Project-A</artifactId>
08       <version>1.0</version>
09       <scope>compile</scope>
10       <optional>true</optional> <!-- value will be true or false only -->
11     </dependency>
12   </dependencies>
13 </project>

可选的依赖工作原理

1 Project-A -> Project-B

上面的图意味着项目A依赖于项目B,当A在它的POM文件中把B声明为一个可选的依赖,他们的关系依然没有改变。仅仅就像一次正常的构建,在这次构建中,项目B将会被添加进classpath。

1 Project-X -> Project-A

但是当一个其他的项目(项目X)在它的POM文件中声明项目A为一个依赖,这个可选的依赖就发挥作用了。你将会注意到项目X的classpath不会包含项目B:为了把B包含进项目X的classpath,你需要在你的POM文件中直接声明。

例子:

有一个名为X2的项目,这个项目和hibernate有一些类似的功能,支持许多数据库驱动/依赖,比如说MySQL,postgre,oracle等。为了构建X2,所有的这些依赖都是必须的,但是对于你的项目来说却不是必须的,所以对于X2把这些依赖声明为可选的是非常实用的,不论什么时候当你在POM文件中把X2声明为一个直接依赖的时候,所有被X2支持的驱动不会自动的被包含进你的项目的classpath,你需要直接声明你将要使用的数据库的依赖/驱动。

依赖排除

因为maven2.X的依赖是传递的,可能会把不想要的依赖包含进你的classpath。比如说 ,你所依赖的项目或许没有正确的设置它们的依赖集。为了处理这种特殊的情况,maven2.x包含了依赖排除的概念。排除在你的POM设置了一个特殊的依赖,并目标到一个特殊的groupId和artifactId,当你构建项目的时候,通过声明排除依赖,这个特殊的artifactId不会被添加到你的项目的classpath中。

怎么使用依赖排除:

在pom文件的<dependency>部分增加<exclusions> 标签:

01 <project>
02   ...
03   <dependencies>
04     <dependency>
05       <groupId>sample.ProjectA</groupId>
06       <artifactId>Project-A</artifactId>
07       <version>1.0</version>
08       <scope>compile</scope>
09       <exclusions>
10         <exclusion>  <!-- declare the exclusion here -->
11           <groupId>sample.ProjectB</groupId>
12           <artifactId>Project-B</artifactId>
13         </exclusion>
14       </exclusions>
15     </dependency>
16   </dependencies>
17 </project>


依赖排除的工作原理和何时使用它(作为最后一招)

1 Project-A
2    -> Project-B
3         -> Project-D <! -- This dependency should be excluded -->
4               -> Project-E
5               -> Project-F
6    -> Project C

上面的图表表示项目A依赖于整个项目B和项目C,项目B依赖于项目D,项目D依赖于项目E和F,默认情况下,项目A的classpath将包含:

1 B, C, D, E, F

因为我们知道项目D的一些依赖在仓库中丢失了,所以,如果我们不想要把项目D和它的依赖添加到项目A的classpath中会怎样呢?并且你不想要项目B中依赖于项目D的某些功能,在这种情况下,项目B的开发者在项目D的依赖上增加<optional> true</optional>标签,就像下面这样:

1 <dependency>
2   <groupId>sample.ProjectD</groupId>
3   <artifactId>ProjectD</artifactId>
4   <version>1.0-SNAPSHOT</version>
5 <optional>true</optional>
6 </dependency>

然而,他们并没有这么做。使用最后的手段,你仍然可以把它排除在外,在项目A中,像这样:

01 <project>
02   <modelVersion>4.0.0</modelVersion>
03   <groupId>sample.ProjectA</groupId>
04   <artifactId>Project-A</artifactId>
05   <version>1.0-SNAPSHOT</version>
06   <packaging>jar</packaging>
07   ...
08   <dependencies>
09     <dependency>
10       <groupId>sample.ProjectB</groupId>
11       <artifactId>Project-B</artifactId>
12       <version>1.0-SNAPSHOT</version>
13       <exclusions>
14         <exclusion>
15           <groupId>sample.ProjectD</groupId> <!-- Exclude Project-D from Project-B -->
16           <artifactId>Project-D</artifactId>
17         </exclusion>
18       </exclusions>
19     </dependency>
20   </dependencies>
21 </project>

如果我们把项目A部署到仓库,并且项目X声明了一个正常的依赖,依赖于项目A,项目D会被从classpath中排除吗?

1 Project-X -> Project-A

答案是yes,项目A已经声明了它不需要项目D,所以项目D不会被传递地带到项目A中。

现在,考虑依赖于项目Y的项目X,就像下面表示的一样:

1 Project-X -> Project-Y
2                -> Project-B
3                     -> Project-D
4                        ...

项目Y同样也有也依赖于项目B,并且它需要一些被项目D支持的特性。因此,不要在这个依赖列表里放置一个对项目D的排除。它或许会供给一个额外的仓库,在这个仓库里,我们可以依赖项目E。在这个例子里,项目D不是被全局排除是非常重要的,因为项目Y有一个合理的依赖。

有另外一种情况,如果我们不想要项目E,而不是项目D,该怎么去排除呢?看看下面的图:

1 Project-A
2    -> Project-B
3         -> Project-D
4               -> Project-E <!-- Exclude this dependency -->
5               -> Project-F
6    -> Project C

整个依赖的排除工作在我们声明的点下进行。如果你想要排除项目E,你只需要改变排除的点,但是你不能在项目D进行排除,你不能改变项目D的POM文件,如果可以,就会使用可选的依赖而不是排除了,或者简单的把项目D分成子模块,

01 <project>
02   <modelVersion>4.0.0</modelVersion>
03   <groupId>sample.ProjectA</groupId>
04   <artifactId>Project-A</artifactId>
05   <version>1.0-SNAPSHOT</version>
06   <packaging>jar</packaging>
07   ...
08   <dependencies>
09     <dependency>
10       <groupId>sample.ProjectB</groupId>
11       <artifactId>Project-B</artifactId>
12       <version>1.0-SNAPSHOT</version>
13       <exclusions>
14         <exclusion>
15           <groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
16           <artifactId>Project-E</artifactId>
17         </exclusion>
18       </exclusions>
19     </dependency>
20   </dependencies>
21 </project>

为什么排除是在每个依赖的基础上,而不是在POM级别

这用来保证依赖图是可预测的,并从排除一个依赖保持继承效果。如果你采取了最后的手段并放置了一个排除,你应该能绝对的确认哪个依赖被带进了一个不想要的传递依赖。

转载自 并发编程网 - ifeve.com

相关文章
|
7月前
|
Java Maven 微服务
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的 maven 依赖
在项目中使用Swagger2工具时,需导入Maven依赖。尽管官方最高版本为2.8.0,但其展示效果不够理想且稳定性欠佳。实际开发中常用2.2.2版本,因其稳定且界面友好。以下是围绕2.2.2版本的Maven依赖配置,包括`springfox-swagger2`和`springfox-swagger-ui`两个模块。
225 0
|
6月前
|
存储 Java Maven
Maven系统级别依赖:解决部署时Jar包缺失问题
以上就是关于Maven系统级别依赖解决部署时Jar包缺失问题的解答,希望对你有所帮助。在软件开发中,遇到问题并解决问题是常态,希望你能够善用这些工具,解决你遇到的问题。
346 28
|
9月前
|
缓存 架构师 Java
Maven实战进阶(01)面试官:Maven怎么解决依赖冲突?| 有几种解决方式
本文介绍了Maven的核心功能和依赖管理技巧。Maven是基于项目对象模型(POM)的构建工具,具备跨平台、标准化、自动化等特性。其三大核心功能为依赖管理、仓库管理和项目构建。依赖管理通过pom.xml文件引入第三方组件并自动下载;仓库管理涉及中央仓库、私服和本地仓库;项目构建则通过生命周期管理编译、测试、打包等流程。文章还详细讲解了依赖冲突的解决方法,包括默认规则、手工排除和版本指定等策略。
|
10月前
|
缓存 Java Maven
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法!在处理Maven项目问题时,首先检查Maven配置是否正确。接着通过“File--Invalidata Caches”清除IDEA缓存并重启。使用Maven命令`mvn dependency:purge-local-repository`和`mvn dependency:resolve`清除本地依赖缓存。最后,在Terminal中输入`mvn clean install`完成构建。
2741 1
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
|
11月前
|
Java Maven
maven打瘦包,且只打入部分想打入的依赖瘦包
maven打瘦包,且只打入部分想打入的依赖瘦包 设计 工程结构分析 环境管理 城市资源 安全工程 工程管理
225 10
|
12月前
|
Java API Apache
除了 Maven,还有哪些工具可以管理项目的依赖和版本冲突
除了Maven,常用的项目依赖管理和版本冲突解决工具有Gradle、Ivy、Ant+Ivy、SBT等。这些工具各有特点,适用于不同的开发环境和需求。
917 2
|
12月前
|
XML 安全 Java
【Maven】依赖管理,Maven仓库,Maven核心功能
【Maven】依赖管理,Maven仓库,Maven核心功能
1919 3
|
3月前
|
Java 区块链 Maven
关于引入maven项目后出现‘parent.relativePath’ of POM错误时的解决方法
关于引入maven项目后出现‘parent.relativePath’ of POM错误时的解决方法
322 3
|
2月前
|
Java jenkins 应用服务中间件
结合Jenkins与Tomcat,实施Maven项目的自动构建和部署流程。
任何项目构建和部署的自动化流程,总离不开对各个环节精细把控与密切配合。涉及到源代码管理、构建工具、持续集成服务器以及最终的运行时环境的协调。通过上述简洁实用的步骤,可以实现Maven项目从源代码到运行状态的无缝过渡,进而提升软件开发的效率与质量。
209 0
|
Java Maven 开发者
maven项目中官方setting.xml文件
`settings.xml` 是 Maven 的配置文件,用于定义用户或全局级别的构建行为。它包含本地仓库路径、网络代理、服务器认证、仓库镜像及构建配置文件等设置,帮助开发者根据环境定制 Maven 行为,提升构建效率与灵活性。
655 0