Maven-Optional Dependencies & Dependency Exclusion
本文讨论可选依赖和排除依赖. 帮助用户理解它们是什么, 如何使用, 它们如何工作, 以及什么时候使用它们最合适. 本文也将解释为什么排除是基于单个依赖的, 而非POM级别的.
Optional Dependencies
可选依赖用在不能真正地将一个项目划分为多个子模块时. 一些依赖只在该项目中的某些特性中使用, 并且如果这些特性没有使用到的话, 这些依赖就不需要. 最理想的情况, 这样的特性会被划分到一个依赖于核心功能工程的子模块, 这个新子模块将只有非可选依赖, 因为一旦你决定使用该子模块的功能, 你就会需要这些依赖.
然而, 如果该项目无法划分, 这些依赖就需要被声明为可选的. 如果一个用户想要使用和一个可选依赖相关的功能, 他们需要在自己的工程里声明那个可选依赖. 这并不是处理这种情况的最清晰的方式.. 但可选依赖和依赖排除都是 stop-gap 方案.
Why use optional dependencies?
声明可选依赖不仅仅在节省内存空间问题上很重要. 当一个用户使用一个工程时, 控制实际需要的依赖列表非常重要. 因为这些jar包可能会最终放入一个WAR, EAR, EJB等等. 包含了错误的jar包, 可能会违反许可协议, 引起路径问题等等.
How do I use the optional tag?
声明一个可选依赖, 只需要在你的依赖声明中简单地设置 <optional> 标签为 true. 如下例所示:

How do optional dependencies work?
Project-A -> Project-B
如果 project A 依赖于 project B, 当A将B声明为可选依赖时, 这个关系就确定下来了. 这就像一个正常的构建, B将会被添加到它的类路径里.
Project-X -> Project-A
但当另一个工程 project X 将工程A声明为它的依赖时, 可选依赖就发挥效用了. 你会发现, 工程B没有被包含到X的类路径中. 你需要在POM中直接声明B, 才能将它包含到X的类路径中.

Example
假设有一个工程名为X2, 它和Hibernate有相似的功能, 支持很多种数据库驱动, 比如mysql, postge, oracle等. 构建X2需要所有这些依赖, 但你的项目未必. 所以, 将这些依赖声明为可选的对X2来说是非常实用的, 这样无论何时你的项目声明了X2作为一个直接依赖, X2支持的所有驱动就不会自动地包含到你的工程的类路径里, 你需要直接声明你需要的数据库驱动.
[注意] 在理想情况下, 不应用使用可选依赖. 在面向对象设计中, 有个单一职责性原则, 意指一个类应该只有一项职责, 而不是糅合太多功能. 这个原则在规划maven项目时也同样适用. 上例中, 更好的做法是为mysql和postgreSQL分别创建一个maven项目, 基于同样的groupId分配不同的artifactId. 在各自的pom中声明对应的jdbc驱动依赖, 不使用可选依赖. 用户根据需要选择使用. 由于传递性依赖的作用, 就不用再声明jdbc驱动依赖了.
Dependency Exclusions
由于maven 2.x的依赖传递规则, 很有可能你的项目类路径中包含了一些不想要的依赖. 比如说, 你的项目依赖的那些工程可能没有正确地声明他们的依赖集合. 为了应对这个特殊的场景, maven2.x提出了依赖排除的概念. 排除是针对POM中的一个特定的依赖设置的, 以一个特定的groupId和artifactId为标识. 如果你声明了排除依赖, 当你构建你的工程时, 该构件就不会被添加到你的工程的类路径中.
How to use dependency exclusions
我们在pom的<dependency>部分添加<exclusions>标签.

How dependency exclusion works and when to use it ( as a last resort! )
如下图所示. 工程A同时依赖于B,C. 而工程B又依赖于D. 默认情况下, A的类路径会包含: B, C, D, E, F.
如果我们不需要使用工程D, 同时不想把它的依赖添加到A的类路径中, 因为我们已知D的某些依赖, 比如说E, 在仓库中找不到了. 而你又不需要工程B中依赖于工程D的那部分功能. 在这种情况下, B的开发者可能会提供一个关于D的可选依赖.
然而!!! 他们没有提供!!! 作为最后的手段, 你依然可以选择在你这一侧把不想要的依赖排除掉.


如果我们将工程A发布到一个仓库, 并且工程X声明一个关于A的普通依赖, 那么D还会被排除在类路径之外吗?
答案是会. 工程A已经声明了它不需要工程D就可以运行, 所以这会产生一个传递的依赖.
现在, 考虑工程X依赖于Y. 工程Y也有一个关于B的依赖, 且它确实需要由工程D支持的特性. 因此, 在它的依赖列表里不会出现排除D的情况. 它也可能提供一个额外的仓库, 在那里我们可以处理工程E. 在这种情况下, 工程D不是全局排除就非常重要了, 因为它是Y的一个合法依赖.
Why exclusions are made on a per-dependency basis, rather than at the POM level
主要是为了确保依赖关系图是可预知的, 避免排除了不应排除的依赖. 如果你需要排除, 你应绝对确定你引入的哪个依赖带来了不必要的依赖传递.
Reference
http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
<Maven实战>
Maven-Optional Dependencies & Dependency Exclusion的更多相关文章
- maven可选依赖(Optional Dependencies)和依赖排除(Dependency Exclusions)
我们知道,maven的依赖关系是有传递性的.如:A-->B,B-->C.但有时候,项目A可能不是必需依赖C,因此需要在项目A中排除对A的依赖.在maven的依赖管理中,有两种方式可以对依赖 ...
- Maven Optional & Exclusions 使用区别
Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反. Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖 ...
- Maven optional关键字透彻图解
写在前面 本来想写一篇「如何自定义Spring Boot Starter」,但是为了更好理解 Starter 的一些设计理念和其中的关键点,所以提前将一些细节内容单独提取出来讲解说明 在 Maven ...
- maven坐标Dependencies和Exclusions详解
1.概念介绍 Dependencies:是可选依赖(Optional Dependencies) Exclusions:是依赖排除(Dependency Exclusions) 2.Dependenc ...
- Maven Optional & Exclusions使用区别
Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反. Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖 ...
- 【dependencyManagement版本管理】dependencies.dependency.version is missing
maven 的gav的v(版本问题) 报错dependencies.dependency.version is missing 出现的场景 一个项目中有多个模块 父模块中出现dependencies. ...
- Maven中<dependencies>节点和<dependencyManagement>节点的区别 转
以前一直没有在意,今天建立maven工程的时候在<dependencyManagement>节点下加入了junit依赖,结果在dependency Graph中没有发现junit的依赖关系 ...
- 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique
2016-10-09 23:14:43.177 DEBUG [restartedMain][org.springframework.core.type.classreading.AnnotationA ...
- 解决eclipse svn 转 maven web 项目中遇到找不到maven managed dependencies的问题
我们在使用eclipse从svn上check项目下来,然后转成maven web 项目的时候,经常会遇到一个问题,就是找不到maven依赖(maven managed dependencies),从而 ...
随机推荐
- Python中__name__属性的妙用
在Python中,每一个module文件都有一个built-in属性:__name__,这个__name__有如下特点: 1 如果这个module文件是被别的文件导入的,那么,该__name__属性的 ...
- 软工实践Alpha冲刺(2/10)
队名:我头发呢队 组长博客 作业博客 杰(组长) 过去两天完成了哪些任务 查看了讯飞开放平台的sdk 查阅了Google Material Design 2的官方文档 接下来的计划 继续打磨UI界面: ...
- 关于char, wchar_t, TCHAR, _T(),L,宏 _T、TEXT,_TEXT、L
char :单字节变量类型,最多表示256个字符, wchar_t :宽字节变量类型,用于表示Unicode字符, 它实际定义在<string.h>里:typedef unsigned s ...
- 转 【.NET平台下使用MongoDB入门教程】
目录 一.了解MongoDB 二.MongoDB特点 三.安装及常用命令 3.1 下载安装 3.2 启动服务器 3.3 常用操作 3.4 其他命令 3.5 做成windows服务 四.批处理程序开启M ...
- Ehcache概念篇
前言 缓存用于提供性能和减轻数据库负荷,本文在缓存概念的基础上对Ehcache进行叙述,经实践发现3.x版本高可用性不好实现,所以我采用2.x版本. Ehcache是开源.基于缓存标准.基于java的 ...
- 如何取得dbgrid中未保存(post)的值(50分)
比如说处在编辑状态时,想取得当前记录值 Dataset.fields[0].Value 就是当前值:Dataset.fields[0].OldValue 就是原始值. 呵呵,我指得是在编辑时,就是按键 ...
- Delphi Code Editor 之 快捷菜单
Code Editor的快捷菜单分为两个部分:编辑器菜单项和调试器菜单项. 调试器菜单项留作以后讲解调试应用程序时再讲,这里只讲讲Code Editor的编辑器快捷菜单项. 下面列出了全部菜单项及描述 ...
- openstack中间件message queue 与memcached环境部署
为什么要安装中间件 组件间的通信使用的是REST API 而组件内部之间的通信则是使用的中间件 首先登陆openstack的官网查看官方文档 www.openstack.org 应为在部署一个架构之前 ...
- [BZOJ2055] 80人环游世世界
Description 想必大家都看过成龙大哥的<80天环游世界>,里面的紧张刺激的打斗场面一定给你留下了深刻的印象.现在就有这么 一个80人的团伙,也想来一次环游世界. 他们 ...
- [洛谷P4139]上帝与集合的正确用法
题目大意:多次询问,每次给你$p$询问$2^{2^{2^{\dots}}}\bmod p$ 题解:扩展欧拉定理,求出$\varphi(p)$即可.因为$2^{2^{2^{\dots}}}>> ...