第五章 坐标和依赖

1.   Maven 定义了这样一组规则:世界上任何一个构件都可以使用 Maven 坐标唯一标识, Maven 坐标的元素包括 groupId artifactId version packaging classifier

 

2.   Maven 内置了一个中央仓库的地址( http://repo1.maven.org/maven2 ),该中央仓库包含了世界上大部分流行的开源项目构件, Maven 会在需要的时候去那里下载。

 

3.   groupId 定义了当前 Maven 项目隶属的实际项目。一个实际项目往往会被划分成很多模块,一个模块可能就是一个 Maven 项目。 goupId 不应该对应项目隶属的组织或公司,因为一个组织或公司可能会有多个实际项目。 groupId 的表示方式与 Java 包名类似。

 

4.   artifactId 定义实际项目中的一个 Maven 项目(模块)。推荐使用实际项目名作为 artifactId 的前缀,如: nexus-indexer 。因为默认情况下 Maven 生成的构件会以 artifactId 开头,用实际项目名作为前缀就能方便从一个 lib 文件夹中找到某个实际项目的一组构件。

 

5.   version 定义了当时 Maven 项目所处的版本。

 

扫描二维码关注公众号,回复: 416495 查看本文章

6.   packaging 定义了 Maven 项目的打包方式,通常与所生成构件的文件扩展名对应。不同的打包方式会影响构建的生命周期。比如 jar 打包与 war 打包会使用不同的命令。不定义 packaging 的时候,默认为 jar 。( package "maven-plugin" 的构件扩展名是 jar

 

7.  classifier 定义构建输出的一些附属构件。附属构件与主构件对应。如 Java 项目的 javadoc sources TestNG 项目默认是基于 Java 1.4 平台的,而它又提供了一个 jdk5 的附属构件。我们不能直接定义项目的 classifier ,因为附属构件不是项目直接默认生成的,而是由附加的插件帮助生成的。

 

8.  g roupId artifactId version 是必须定义的, packaging 是可选的, classifier 是不能直接定义的。

 

 

9.   项目构件的文件名与坐标相对应,一般为: artifactId-version[-classifier].packaging

 

10.   mvn clean install 会根据 POM 配置自动下载所需要的构件,执行编译、测试、打包等工作,最后将项目生成的构件安装到本地仓库中。

 

11.   根元素 project 下的 dependencies 可以包含一个或者多个项目依赖。一个依赖声明可以包含如下的一些元素:

<dependency>

  <groupId>…</groupId>

  <artifactId>…</artifactId>

  <version>…</version>

  <type>…</type>

  <scope>…</scope>

  <optional>…</optional>

  <exclusions>

    <exclusion>…</exclusion>

    …

  </exclusions>

</dependency> 
 

groupId artifactId version 是依赖的基本坐标。 type 为依赖的类型,对应于项目坐标定义的 packaging scope 是依赖的范围。 optional 标记依赖是否是可选的。 exclusions 用来排除传递性依赖。

 

12.   依赖范围包含:

Compile :编译依赖范围。对于编译、测试、运行三种 classpath 都有效。是默认的依赖范围。

Test :测试依赖范围。只对测试 classpath 有效。如 Junit

Provided :已提供依赖范围。只对编译、测试 classpath 有效。如 servlet-api ,运行时容器已提供。

Runtime :运行依赖范围。只对测试和运行 classpath 有效。如 JDBC 驱动实现,编译主代码时只需要 JDK 提供的 JDBC 接口。

System :系统依赖范围。与 Provided 依赖范围一致。但依赖是通过 systemPath 元素显式指定文件的路径,与本机系统绑定,一般无法移植。

Import :导入依赖范围。不会对 3 classpath 产生实际影响。

scope

compile classpath

test classpath

runtime classpath

example

compile

Y

Y

Y

spring-core

test

-

Y

-

Junit

provided

Y

Y

-

servlet-api

runtime

-

Y

Y

JDBC 驱动实现

system

Y

Y

-

本地的Maven 类库文件

 

13.   Maven 会解析各个直接依赖的 POM, 将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。假设 A 依赖 B B 依赖 C ,我们称 A B 是第一直接依赖, B C 是第二直接依赖, A C 是传递依赖。下表显示了三者的关系:

第一          第二

compile

test

provided

runtime

compile

compile

-

-

runtime

test

test

-

-

test

provided

provided

-

provided

provided

runtime

runtime

-

-

runtime

疑问:为什么 compile + provided --> no dependency ? provided + provided --> provided ? 个人认为此表完全不对。。。

 

14.   依赖调解第一原则:路径最近:

A->B->C->X(1.0) A->D->X(2.0)  X->2.0

依赖调解第二原则:最先声明:

A->B->X(1.0) A->D->X(2.0) B D 先声明, X->1.0

 

15.   如果项目 B 实现了两个特性,特性一依赖于项目 X ,特性二依赖于项目 Y ,而 X Y 是互斥的。(比如 B 是一个持久层隔离包,支持多种数据库, X MySQL 驱动, Y PostgreSQL 驱动。)那么 X Y B 的可选依赖。如果 A 依赖 B ,则 A 不再传递依赖 X Y 而需要显式地声明 X Y 为其直接依赖。

 

16.   有时候希望排除某些传递依赖(比如传递依赖因版权限制不可用或者传递依赖是个 SNAPSHOT 版本)而显示地声明他们的替代者。可以在 <exclusion> 中声明想排除的传递依赖,而多增加一个 <dependency> 声明它的替代者。 <exclusion> 只用声明 groupId artifactId 就行。

 

17.   对于来自同一个实际项目的多个项目依赖,他们版本应该是一致的,这样,可以先用 <properties> 定义一个版本号变量。如

<properties><spring.version>2.5.6</spring.version></properties>

然后在版本信息的位置使用 ${spring.version} 来引用它。

 

18.   可以执行 mvn dependency:list mvn dependency:tree 查看已解析的依赖( resolved dependency )。

 

19.   可以执行 mvn dependency:analyze 来分析项目中的直接用到但未显示声明的依赖( Used undeclared dependencies )和声明了但未用到的依赖( Unused declared dependencies )。 Used undeclared dependencies 是项目直接用到了,但通过传递依赖引入的项目,这样当项目的直接依赖更新时,传递依赖也会随之更新,从而会导致项目代码与传递依赖不兼容。 Unused declared dependencies 并不是完全没用的依赖,只是在编译主代码和测试代码时没用,但可能会在执行测试和运行时用到。

猜你喜欢

转载自seanzhou.iteye.com/blog/1290558