本文讨论可选依赖和排除依赖.  帮助用户理解它们是什么, 如何使用, 它们如何工作, 以及什么时候使用它们最合适. 本文也将解释为什么排除是基于单个依赖的, 而非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的更多相关文章

  1. maven可选依赖(Optional Dependencies)和依赖排除(Dependency Exclusions)

    我们知道,maven的依赖关系是有传递性的.如:A-->B,B-->C.但有时候,项目A可能不是必需依赖C,因此需要在项目A中排除对A的依赖.在maven的依赖管理中,有两种方式可以对依赖 ...

  2. Maven Optional & Exclusions 使用区别

    Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反. Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖 ...

  3. Maven optional关键字透彻图解

    写在前面 本来想写一篇「如何自定义Spring Boot Starter」,但是为了更好理解 Starter 的一些设计理念和其中的关键点,所以提前将一些细节内容单独提取出来讲解说明 在 Maven ...

  4. maven坐标Dependencies和Exclusions详解

    1.概念介绍 Dependencies:是可选依赖(Optional Dependencies) Exclusions:是依赖排除(Dependency Exclusions) 2.Dependenc ...

  5. Maven Optional & Exclusions使用区别

    Optional和Exclusions都是用来排除jar包依赖使用的,两者在使用上却是相反. Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖 ...

  6. 【dependencyManagement版本管理】dependencies.dependency.version is missing

    maven 的gav的v(版本问题) 报错dependencies.dependency.version is missing 出现的场景 一个项目中有多个模块 父模块中出现dependencies. ...

  7. Maven中<dependencies>节点和<dependencyManagement>节点的区别 转

    以前一直没有在意,今天建立maven工程的时候在<dependencyManagement>节点下加入了junit依赖,结果在dependency Graph中没有发现junit的依赖关系 ...

  8. 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique

    2016-10-09 23:14:43.177 DEBUG [restartedMain][org.springframework.core.type.classreading.AnnotationA ...

  9. 解决eclipse svn 转 maven web 项目中遇到找不到maven managed dependencies的问题

    我们在使用eclipse从svn上check项目下来,然后转成maven web 项目的时候,经常会遇到一个问题,就是找不到maven依赖(maven managed dependencies),从而 ...

随机推荐

  1. Python中的namespace package

    在Python 3.3之前,一个目录想被当成package被导入,必须包含__init__.py文件:而在Python 3.3及以后的版本中,__init__.py文件可以不需要,直接使用import ...

  2. Comparison of Android versions(strcmp的应用)

    Description As an Android developer, itˇs really not easy to figure out a newer version of two kerne ...

  3. 软件工程 作业part3 读后感

    匆匆看完构建之法,觉得这种不认真看完书就去写随笔去评价这本书是对作者的不尊重,所以觉得应该提问题和写感悟. 我的一点拙见,提的问题在现在这个信息发达的时候感觉只要有时间都可以自己解决. 感觉软件工程这 ...

  4. Thunder团队第六周 - Scrum会议2

    Scrum会议2 小组名称:Thunder 项目名称:i阅app Scrum Master:宋雨 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康 ...

  5. Alpha-5

    前言 失心疯病源5 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 今天完成了那些任务 14:30~15:30 阅读blob分析相关论文,找到一篇很早年的论文,但是作者讲解十分细 ...

  6. iOS开发跳转指定页面

    for (UIViewController *VC in self.navigationController.viewControllers) { if ([VC isKindOfClass:[Car ...

  7. HDU 2163 Palindromes

    http://acm.hdu.edu.cn/showproblem.php?pid=2163 Problem Description Write a program to determine whet ...

  8. 《Effective C#》快速笔记(三)- 使用 C# 表达设计

    目录 二十一.限制类型的可见性 二十二.通过定义并实现接口替代继承 二十三.理解接口方法和虚方法的区别 二十四.用委托实现回调 二十五.用事件模式实现通知 二十六.避免返回对内部类对象的引用 二十七. ...

  9. ibatsi学习总结

    学习来源:黑马程序员 先总结一下遇到的问题 问题1:1,resultMap 可以不写,比如配置1 配置1: <typeAlias alias="puser" type=&qu ...

  10. spring cloud 之 客户端负载均衡 Ribbon

    一.负载均衡 负载均衡(Load Balance): 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性.其意 ...