依赖是Maven中最关键的部分,使用Maven管理项目很大的原因是因为他的依赖管理功能。
全部章节传送门:
Maven学习笔记(一):Maven概述
Maven学习笔记(二):Maven依赖
Maven学习笔记(三):POM文件
Maven学习笔记(四):Maven仓库
Maven学习笔记(五):Maven插件
在工程中引入某个jar包,只需要在pom.xml中引入jar包的坐标,比如引入log4j的依赖:
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>compile</scope>
</dependency>
</dependencies>
Maven通过groupId、artifactId与version三个向量来定位Maven仓库其jar包所在的位置,并把对应的jar包引入到工程中来。
依赖范围
maven 项目不同的阶段引入到classpath中的依赖是不同的,例如,编译时,maven 会将与编译相关的依赖引入classpath中,测试时,maven会将测试相关的的依赖引入到classpath中,运行时,maven会将与运行相关的依赖引入classpath中,而依赖范围就是用来控制依赖于这三种classpath的关系。
前面的例子中,scope标签就是依赖范围的配置。该项默认配置compile,可选配置还有test、provided、runtime、system、import,其中compile、test和provided使用较多,下面依次介绍。
编译依赖范围(compile)
该范围就是默认依赖范围,此依赖范围对于编译、测试、运行三种classpath都有效,举个简单的例子,假如项目中有spring-core的依赖,那么spring-core不管是在编译,测试,还是运行都会被用到,因此spring-core必须是编译范围(构件默认的是编译范围,所以依赖范围是编译范围的无须显示指定)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5</version>
<scope>compile</scope> <!--默认为该依赖范围,无须显示指定-->
</dependency>
测试依赖范围(test)
使用此依赖范围的依赖,只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖,最典型的例子就是 Junit, 构件在测试时才需要,所以它的依赖范围是测试,因此它的依赖范围需要显示指定为<scope>test</scope>,当然不显示指定依赖范围也不会报错,但是该依赖会被加入到编译和运行的classpath中,造成不必要的浪费 。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
已提供依赖范围(provided)
使用该依赖范围的maven依赖,只对编译和测试的classpath有效,对运行的classpath无效,典型的例子就是servlet-api, 编译和测试该项目的时候需要该依赖,但是在运行时,web容器已经提供的该依赖,所以运行时就不再需要此依赖,如果不显示指定该依赖范围,并且容器依赖的版本和maven依赖的版本不一致的话,可能会引起版本冲突,造成不良影响。
<dependency>
<groupId>javax-servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
运行时依赖范围(runtime)
使用该依赖范围的maven依赖,只对测试和运行的classpath有效,对编译的classpath无效,典型例子就是JDBC的驱动实现,项目主代码编译的时候只需要JDK提供的JDBC接口,只有在测试和运行的时候才需要实现上述接口的具体JDBC驱动。
系统依赖范围(system)
该依赖与classpath的关系与provided依赖范围完全一致,但是系统依赖范围必须通过配置systemPath元素来显示指定依赖文件的路径,此类依赖不是由maven仓库解析的,而且往往与本机系统绑定,可能造成构件的不可移植,因此谨慎使用,systemPath元素可以引用环境变量:
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
导入依赖范围(import)
该依赖范围不会对三种classpath产生影响,该依赖范围只能与dependencyManagement元素配合使用,其功能为将目标pom文件中dependencyManagement的配置导入合并到当前pom的dependencyManagement中。有关dependencyManagement的功能会在Maven继承特性部分说明。
依赖的传递
依赖的传递性指:在A中添加对B的依赖,在B中添加对C的依赖,如果依赖范围是compile的,A不仅会有B的jar 包,也会有C的jar 包。如果在C中添加了某个依赖,那么根据传递性,A和B也可以使用C添加的依赖,而不需要自己再重新引入依赖。
依赖传递的原则:
- 最短路径优先原则:如果A依赖于B,B依赖于C,在B和C 中同时有log4j的依赖,并且这两个版本不一致,那么A会根据最短路径原则,在A中会传递过来B的log4j版本。
- 路径相同先声明原则:如果在A同时依赖于B和C,B和C没有依赖关系,并且都有log4j的依赖,且版本不一致,那么A会引入在pom.xml中先声明依赖的log4j版本。
依赖的排除
我们在当前工程中引入了A的依赖,而A同时有对B的依赖,根据传递性我们知道,在当前工程中会自动引入对B的依赖。如果我们不想引入对B的依赖,我们就需要在引入对A依赖的同时排除对B的依赖。
下面我们以spring-core为例,当我们在pom.xml中引入对spring-core 的同时,会自动将commons-logging 的jar 包引入进来,如果我们不想引入commons-logging,就可以进行如下配置:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.14.RELEASE</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exlcusion>
</exclusions>
</dependency>
</dependencies>
聚合和继承
将多个项目同时运行就称为聚合。只需在pom文件中作如下配置即可实现聚合:
<modules>
<module>web-connection-pool</module>
<module>web-java-crawler</module>
</modules>
另外,聚合模块的打包方式必须为pom,否则无法完成构建。
在聚合多个项目时,如果这些被聚合的项目中需要引入相同的Jar,那么可以将这些Jar写入父pom中,各个子项目继承该pom即可。,父模块的打包方式必须为pom,否则无法构建项目。
通过在各个子模块中配置来表明其继承与哪一个父模块:
<parent>
<groupId>com.baidu</groupId>
<artifactId>miliao-rootpom</artifactId>
<version>2.0.3</version>
</parent>
继承的POM元素如下:
- groupId:项目组ID,项目坐标的核心元素
- version:项目版本,项目坐标的核心因素
- description:项目的描述信息
- organization:项目的组织信息
- inceptionYear:项目的创始年份
- url:项目的URL地址
- developers:项目的开发者信息
- contributors:项目的贡献者信息
- distributionManagement:项目的部署配置
- issueManagement:项目的缺陷跟踪系统信息
- ciManagement:项目的持续集成系统信息
- scm:项目的版本控制系统
- malilingLists:项目的邮件列表信息
- properties:自定义的Maven属性
- dependencies:项目的依赖配置
- dependencyManagement:项目的依赖管理配置
- repositories:项目的仓库配置
- build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
- reporting:包括项目的报告输出目录配置、报告插件配置等
网友评论