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),从而 ...
随机推荐
- Alpha冲刺——第一天
Alpha第一天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...
- C# Excel2007 导出生成 2003兼容格式
//导出2007格式 AppWb.Saved = true; //保存工作薄 AppExcel.ActiveWorkbook.SaveCopyAs(FilePath); //导出2003格式 AppW ...
- java 基础--继承--007
1,子类只能继承父类所有非私有成员 2,子类不能继承父类的构造方法,但可以通过super去访问父类构造方法 3,子类成员变量和父类成员变量名称不一样,如果一样类似于重写,按子类处理,如果一样,就近原则 ...
- vs中编译连接时的警告屏蔽
编译警告类型为warning C4996的形式 可以采用的#pragma warning(disable:4996)屏蔽掉这种编译警告 连接警告类型为warning LNK4049的形式 这是由于不同 ...
- Oracle 11g 体系结构--数据字典
DD:存放数据库内部信息的地方,用于描述数据库内部的运行和管理情况. Oracle数据字典的名称由前缀和后缀组成,使用_连接,含义说明如下: dba_:包含数据库实例的所有对象信息 v$_:当前实例的 ...
- 【Python】PYTHON中STRIP()方法学习笔记
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格). 当使用strip('xxx'),只要字符串头尾有"xxx"中的一个,就会去掉,而不是符合字符串''x ...
- C++面向对象编程,继承,数据抽象,动态绑定
派生类(derived class)能够继承基类(base class )定义的成员: 1).派生类可以无需改变而使用那些与派生类具体特性不相关的操作 2).可以重新定义那些与派生类相关的成员函数,将 ...
- RT-thread组件初始化代码分析
RT-thread提供了组件化功能,具体实现是在components/init文件夹下components.c文件中实现的.应用组件化功能首先在rtconfig.h中添加宏定义#define RT_U ...
- BZOJ 1082 栅栏(二分+DFS剪枝)
首先,长度短的木板一定比长度长的木板容易得到,因此若要得到最多的木板,它们必定是所有木板中最短的——可以对木板排序后二分答案(用k表示). 判断是否合法就用搜索,但数据有点大,要用到两个剪枝.一个是若 ...
- C# 跨服务大文件复制
跨服务的大文件复制,肯定要和本地大文件复制一样,分多次传递,要不然内存也承受不了,下面就说下如何实现大文件的跨服务复制······ 首先肯定要建立一个WCF的服务以及对应的客户端来测试服务,此方法请参 ...