可选依赖(Optional Dependencies)
声明可选依赖不只是为了节省空间或内存等,也为了控制需要的实际依赖列表,因为这些依赖jar包最终会被打包成WAR\EAR等,包含错误的jars可能会引起类路径的一些问题。
在依赖声明中设置<optional>的值为true,就可以将它设为可选依赖。
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
如果A依赖B,当在A的POM中将B声明为可选依赖时,这只是正常的关系:B将被加到A的类路径中。
现在,又有X依赖于A,这时可选依赖就产生效果了,你会发现在X的类路径中并没有包含B,如果想要包含B,需要直接声明B依赖。
依赖排除(Dependency Exclusions)
Maven2引入了依赖传递后,使得有可能将不想要的依赖被包含进自己的项目中,比如当你依赖的项目没有正确的声明它们的依赖时。为了解决这个问题,Maven2引入了依赖排除的概念。依赖排除是针对指定groupId和artifactId的依赖设置的。当你构建项目时,该组件将不会被加入类路径中。
在<dependency>元素下添加<exclusions>子元素表示排除的依赖。
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
假设A依赖B和C,B依赖D,D依赖E和F,默认A的类路径中应该包含:B,C,D,E,F
A
---> B
---> D <!-- 需要排除D -->
--->E
--->F
---> C
如果我们不想将D和它的依赖被添加到A的类路径中(因为我们知道仓库中可能没有E,而且你不想使用B中依赖于D的某个功能),这时候有两种做法,一是使用上面的可选依赖——让B的开发者将D依赖设置为可选。另一种方式则可以在A这里进行控制:
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>sample.ProjectD</groupId><!-- 将D从B中排除 -->
<artifactId>Project-D</artifactId>
</exclusion>
</exclusions>
</dependency>
X ---> A
如果此时将A部署到仓库,X引用A作为依赖,D会从X的类路径中被排除吗?当然,因为A中已经声明不需要D,所以A不会将D传递给X。
X ---> Y
---> B
---> D
考虑这样的情况:现在X依赖Y,Y又依赖B,并且它需要D提供的一项功能。那么它不会从依赖列表中排除D。在这种情况下,不全局性的排除D就显得很重要,因为D是Y的一个合法依赖。
A
---> B
---> D
--->E <!-- 排除它 -->
--->F
如上所示的一种情况,如果要排除的是E而不是D呢?
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0-SNAPSHOT</version>
<packing>jar</packing>
...
<dependencies>
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>sample.ProjectE</groupId> <!-- 从B中排除E -->
<artifactId>Project-E</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
注:依赖排除是以单个依赖为操作基础的,不是POM的全局性设置。