1、依赖的配置
依赖配置的属性:
<dependencies>
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<type>...</type>
<scope>...</scope>
<optional>...</optional>
<exclusions>
<exclusion>...</exclusion>
</exclusions>
</dependency>
</dependencies>
- groupId、artifactId和Version:依赖的基本坐标,Maven根据坐标找到相应的依赖。
- type:依赖的类型,对应于项目坐标定义的packaging。默认为jar
- scope:依赖的范围
- optional:标记依赖的可选性
- exclusions:用来排出传递性的依赖
2、依赖的范围
maven有六种依赖范围compile、test、provided、runtime、system和import(Maven2.0.9及以上)
- compile:编译依赖范围。默认配置。对于编译、测试和运行的classpath都有效。
- test:测试依赖范围。对于测试的classpath有效。例如JUnit
- provided:已提供依赖范围。对于编译、测试有效。运行时无效。如servlet-api,编译测试的时候需要但是运行时在服务器提供,就不需要了。
- runtime:运行时依赖。对于测试和运行有效。编译无效。
- system:系统范围依赖。与provide几乎一致。
<dependency> <groupId>javax.sql</groupId> <artifactId>jdbc-stdext</artifactId> <version>2.0</version> <scope>system</scope> <systemPath>${java.home}/lib/rt.jar</systemPath> </dependency>
- import:导入依赖范围。不对三种classpath有影响。
3、传递性依赖
一个基于Spring Framework的项目,如果不适用Maven,在项目中就需要手动下载依赖。而Spring Framework又依赖其他的开源类库,所以还要下载别的jar包。Maven的传递依赖机制可以解决这个问题。Maven会解析各个直接依赖的POM,将那些必要的简介依赖以传递依赖的形式引入到当前的项目中。
compile | test | provided | runtime | |
compile | compile | -- | -- | runtime |
test | test | -- | -- | test |
provided | provided | -- | provided | provided |
runtime | runtime | -- | -- | runtime |
可以看到当第二直接依赖范围是compile时,传递依赖的范围与第一依赖相同;当第二直接依赖范围是test时,依赖不会传递;当第二直接依赖是provided时,只有第一直接依赖是provided时,传递依赖才是provided;当第二直接依赖的范围是runtime时,传递依赖范围与第一依赖相同,出了compile的范围,这时候传递依赖为runtime。
4、依赖的调解
当依赖传递造成问题时,我们需要清楚地知道该传递性依赖的路径。依赖调解的第一原则是:路径最近着优先。例如项目A有这样的依赖关系:A-->B-->C--X(1.0) A--D--X(2.0),其中X(1.0)的路径长度为3,而X(2.0)的长度为2,因此X(2.0)会被解析使用。
当第一条原则不能解决问题时,使用依赖调解的第二原则:第一声明优先。如A-->B-->Y(1.0) A-->C--Y(2.0)此时依靠第一原则无法判断,这是后在POM中依赖的声明顺序决定了谁会被解析使用。顺序最靠前的会被解析。
5、可选依赖
有一个项目实现了两个特性,其中一个特性依赖与X,另一个特性依赖与Y,而这两个特性是互斥的,用户不可能同时使用两个特性。那么在依赖属性中添加Optional元素。表名为可选依赖。只会对当前项目有影响,而不会传递。
6、最佳实现
1、排除依赖
传递性依赖会给项目隐式的引入很多依赖,这简化了项目依赖的管理。有时候也会带来问题。当一个项目有第三方依赖,而这个第三方依赖引用了一个类库的SNAPSHOT版本,而这个依赖会传递到项目中。造成项目的不稳定性。或者引用的类库不在Maven的中央类库中。我们想把这种有危害的依赖踢出。可以使用exclusion元素:
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<exclusions>
<exclusion>
<groupId>com.test</groupId>
<artifactId>project-a</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project-a</artifactId>
<version>1.1.0</version>
</dependency>
这样我们就可以把project-a不稳定的版本踢出,添加一个新的版本1.1.0.。
2、归类依赖
可以在POM文件中增加属性如:
<properties>
<spring-version>4.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring-version}</version>
</dependency>
这样当我们要修改版本的时候,只需要修改property的值就可以了。
3、优化依赖
我们可以通过命令查看当前项目已解析的依赖:
mvn dependency:list
[INFO] ------------------------------------------------------------------------
[INFO] Building Account Email 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:list (default-cli) @ account-email ---
[INFO]
[INFO] The following files have been resolved:
[INFO] commons-logging:commons-logging:jar:1.2:compile
[INFO] junit:junit:jar:4.7:test
[INFO] org.springframework:spring-beans:jar:4.1.3.RELEASE:compile
[INFO] org.springframework:spring-expression:jar:4.1.3.RELEASE:compile
[INFO] javax.activation:activation:jar:1.1:compile
[INFO] org.springframework:spring-aop:jar:4.1.3.RELEASE:compile
[INFO] org.springframework:spring-core:jar:4.1.3.RELEASE:compile
[INFO] aopalliance:aopalliance:jar:1.0:compile
[INFO] org.springframework:spring-context:jar:4.1.3.RELEASE:compile
[INFO] com.icegreen:greenmail:jar:1.3.1b:compile
[INFO] org.springframework:spring-context-support:jar:4.1.3.RELEASE:compile
[INFO] org.slf4j:slf4j-api:jar:1.3.1:compile
[INFO] javax.mail:mail:jar:1.4.1:compile
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.686 s
[INFO] Finished at: 2014-12-20T14:13:26+08:00
[INFO] Final Memory: 7M/12M
[INFO] ------------------------------------------------------------------------
我们可以看到所有的依赖及其依赖范围。
同时可以使用命令查看以来的结构:
mvn dependency:tree
得出结果如下:
[INFO] ------------------------------------------------------------------------
[INFO] Building Account Email 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ account-email ---
[INFO] com.juven.mvnbook.account:account-email:jar:1.0.0-SNAPSHOT
[INFO] +- org.springframework:spring-core:jar:4.1.3.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.2:compile
[INFO] +- org.springframework:spring-beans:jar:4.1.3.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:4.1.3.RELEASE:compile
[INFO] | +- org.springframework:spring-aop:jar:4.1.3.RELEASE:compile
[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] | \- org.springframework:spring-expression:jar:4.1.3.RELEASE:compile
[INFO] +- org.springframework:spring-context-support:jar:4.1.3.RELEASE:compile
[INFO] +- javax.mail:mail:jar:1.4.1:compile
[INFO] | \- javax.activation:activation:jar:1.1:compile
[INFO] +- junit:junit:jar:4.7:test
[INFO] \- com.icegreen:greenmail:jar:1.3.1b:compile
[INFO] \- org.slf4j:slf4j-api:jar:1.3.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.656 s
[INFO] Finished at: 2014-12-20T14:15:52+08:00
[INFO] Final Memory: 6M/12M
[INFO] ------------------------------------------------------------------------
同时可以使用另外一个指令来分析依赖的关系及完整性:
mvn dependency:analyze
结果中指出我们需要的依赖及没有使用的依赖:
[INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ account-email ---
[WARNING] Used undeclared dependencies found:
[WARNING] org.springframework:spring-context:jar:4.1.3.RELEASE:compile
[WARNING] Unused declared dependencies found:
[WARNING] org.springframework:spring-core:jar:4.1.3.RELEASE:compile
[WARNING] org.springframework:spring-beans:jar:4.1.3.RELEASE:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.701 s
[INFO] Finished at: 2014-12-20T14:18:28+08:00
[INFO] Final Memory: 7M/13M
[INFO] ------------------------------------------------------------------------
而这种依赖的出错时很难查找的,所以先进性依赖的分析是非常有用的。