Maven的依赖

jopen 10年前

说说Maven的依赖。
依赖类型
Maven会用到的依赖基本就是5种,compile,test,provided,runtime,system
1.compile:编译依赖范围,默认使用该范围。编译、测试、运行都有效
2.test:测试依赖范围。支队测试的classpath有效。例如Junit,greenMail。
3.provided:对编译和测试有效,对运行无效,常用于容器提供了的运行环境。例如servlet-api,容器以提供,所以只需要编译和测试有效即可。
4.runtime:运行时依赖范围。例如jdbc驱动,编译和测试并不需要,只需要使用JDK提供的JDBC接口即可。
5.system:系统依赖范围,依赖Maven仓库意外的依赖。
例如



<dependencies>      <dependency>        <groupId>javax.sql</groupId>        <artifactId>jdbc-stdext</artifactId>        <version>2.0</version>        <scope>system</scope>     <systemPath>${java.home}/lib/rt.jar</systemPath>      </dependency>    </dependencies>

依赖的传递
项目中,其实经常会出现这种情况,应用了某个Jar包,然后使用时候报错缺少某个类,这就是因为缺少了该jar包所依赖的jar包的原因。例如工程A依赖了,spring-core,spring-core依赖commons-logging,那A依赖spring-core时候依旧传递的依赖了commons-logging。

##传递依赖的范围
假设A依赖B,B依赖C,我们说A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围,如下图,最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间交叉单元格表示传递性依赖范围。
   Tables      compile       test  provided      runtime 
------------- :-------------: -----: :-------------: --------:
compile       compile          X       X          runtime 
test          test             X       X            test   
provided      provided         X   provided         provided
runtime       runtime          X       X            runtime

注意:X代表不依赖

依赖冲突的调解
有两个原则,第一原则是路径短优先原则,第二原则是先声明者优先

##路径短优先原则
依赖调解的第一原则是:路径最近者优先。
A ->B->C->X(1.0)
A ->D->X(2.0)

这样A会传递性依赖X(2.0)

##先声明者优先原则
赖调解的第二原则是:先声明者优先。
当路径长度相同时候,第一原则已经不能解决问题了,Maven2.0.9以后版本就有了第二原则,声明在先者有效。
A ->C->X(1.0)
A ->D->X(2.0)

这样A传递性依赖了X(1.0),因为他是先声明的。

可选依赖
可选依赖不被传递。例如下例,B有一个持久层工具包依赖,他依赖了两种数据库驱动,这两种特性只需要选择一种,这种传递性依赖是不会给传递的,需要在A项目中另外依赖数据库驱动依赖。
<dependency>        <groupId>mysql</groupId>        <artifactId>mysql-connector-java</artifactId>        <version>5.1.10</version>        <option>true</option>      </dependency>   <dependency>        <groupId>postgresql</groupId>        <artifactId>postgresql</artifactId>        <version>8.4.701.jdbc3</version>        <option>true</option>      </dependency>

正常情况不应该使用可选依赖,可选依赖一般是项目有多个特性,在面向对象设计中单一原则意指一个类应该只有一项职责。

排除依赖
有的时候传递性依赖的依赖包还处于不稳定版本,或者传递性依赖包因为版权问题不存在于中央仓库,这时候需要引入其他等价的依赖包。
所以需要排除依赖,然后自己在配置文件中再引入相应的依赖包。

<dependency>           <groupId>org.springframework</groupId>         <artifactId>spring-core</artifactId>         <version>2.5.6</version>         <exclusions>               <exclusion>                        <groupId>commons-logging</groupId>                            <artifactId>commons-logging</artifactId>               </exclusion>         </exclusions>    </dependency>   <dependency>           <groupId> commons-logging </groupId>         <artifactId> commons-logging </artifactId>         <version>1.1.0</version>    </dependency>

归类依赖
有时候,像Spring框架,当更新依赖时候,需要更新一片的依赖关系,这时候一个一个去修改过于麻烦,不如定义一个常量,更新时候手动修改一个就好了。
可以在pom.xml文件中的project标签下,定义
<properties>   <springframework.version>2.5.6</ springframework.version>  </ properties>


然后引入依赖时候,在version 中使用 ${ springframework.version }即可。

依赖优化

##依赖列表
mvn dependency:list命令可以列出当前所有依赖(包括直接和传递)的列表,以及范围。
##依赖树
mvn dependency:tree命令可以层次化的列出所有依赖,可以从书中看出依赖传递的关系。
##依赖分析
mvn dependency:analyze命令可以分析当前依赖,包括哪些依赖被import却没引入,哪些引来引入了但是没加入编译。有时候可以用来删除一些没用的依赖,但是不能直接删除,比如sprint-core是Spring的必须依赖,但是会提示没加入编译,但是他又是Spring框架必须的。
Unused declared dependencies 后的内容 : 项目中未使用的,但显示声明的依赖
Used undeclared dependencies 后的内容:项目中使用到的,但是没有显示声明的依赖。