1.1何ؓmaven坐标
Mavne的一大功能是理目依赖Qؓ了能自动化的解析M一个Java构gQmaven必d它们唯一标识Q这׃赖管理的底层基础—-坐标?/p>
Maven的世界中拥有数量非常巨大的构Ӟ也就是^时用的一些jar、war{文Ӟ在Maven些构件引入坐标概念之前,我们无法使用M一U方式来唯一标识所有这些构件。因此maven定义了这L规则Q世界上M一个构仉可以使用Maven坐标唯一标识Qmaven坐标元素包括groupId、artifactId、version、packaging、classifier。现在,只要我们提供正确的坐标元素,mavenp扑ֈ对应的组件。比如说Q当需要用Java5q_上TestNG?.8版本Ӟ告诉MavenQ?#8220;groupId=org.testng;artifactId=testng;version=5.9;classifier=jdk15
”Qmaven׃从仓库中L相应的构件供我们使用。Maven是从哪里下蝲构g的呢Qmaven内置了一个中央仓库的地址Qhttp://repol.maven.org/maven2Q,该中央仓库包含了世界上大部分行的开源项目组Ӟmaven会在需要的时候去那里下蝲?/p>
1.2坐标详解
先看一l坐标定义,如下Q?/p>
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>
q是nexus-indexer的坐标定义,nexus-indexer是一个对maven仓库~纂索引q提供搜索功能的cdQ它是Nexus目的一个子模块。下面解释一下各个坐标元素:
上述五个元素中,groupId、artifactId、version是必d义的Qpackaging是可选的Q默认ؓjarQ,而classifier是不能直接定义的?/p>
理解清楚Maven坐标之后Q我们就能开始讨论Maven的依赖管理了?/p>
1.3依赖的配|?/p>
一个依赖声明可以包含如下的一些元素:
<project>
…
<dependencies>
<dependency>
<groupId>…</groupId>
<artifactId>…</artifactId>
<version>…</version>
<type>…</type>
<scope>…</scope>
<optional>…</optional>
<exclusions>
<exclusion>
…
</exclusion>
…
</exclusions>
</dependency>
…
</dependencies>
…
</project>
Dependencies可以包含一个或者多个dependency元素Q以声明一个或者多个项目依赖。每个依赖可以包含的元素有:
1.4依赖范围
首先需要知道,Maven在编译项目主代码的时候需要用一套classpath。其ơ,Maven在编译和执行试的时候会使用另外一套classpath。最后,实际q行Maven目的时候,又会使用一套classpath?/p>
依赖范围是用来控制依赖与这三种classpathQ编译classpaht、测试classpath、运行classpathQ的关系QMaven有以下几U依赖范_
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/tr.jar</systemPath>
</dependency>
1.5传递性依?/p>
何ؓ传递性依赖?现在举一个例子:目中有一个compile范围的spring-core依赖Qspring-core有一个compile范围的commons-logging依赖Q那么commons-logging׃成ؓ该项目的compile范围依赖Qcommons-logging是该目的一个传递依赖?/p>
Maven会解析各个直接依赖的POMQ将那些必要的间接依赖以传递性依赖的形式引入到当前项目中?/p>
依赖范围不仅可以控制依赖与三Uclasspath的关p,q对传递性依赖生媄响。假设A依赖于BQB依赖于CQ我们说A对于B是第一直接依赖QB对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和W二直接依赖的范围决定了传递性依赖的范围Q如表,最左边一列表C第一直接依赖范围Q最上面一行表C第二直接依赖范_中间的交叉单元格则表CZ递性依赖范?/p>
compile |
test |
provided |
runtime | |
compile |
compile |
—— |
—— |
runtime |
test |
test |
—— |
—— |
test |
provided |
provided |
—— |
provided |
provided |
runtime |
runtime |
—— |
—— |
runtime |
仔细观察一下表可以发现q样的规律:当第二直接依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一_当第二直接依赖的范围是test的时候,依赖不会得以传递;当第二直接依赖的范围为provided的时候,只传递第一直接依赖的范围ؓprovided的依赖,且传递性依赖的范围同样为providedQ当W二直接依赖的范围是runtime的时候,传递性依赖的范围与第一直接依赖的范围一_但compile除外Q此时传递性依赖的范围为runtime?/p>
1.6依赖调解
Maven引入的传递性依赖机Ӟ一斚w大大化和方便了依赖声明,另一斚wQ大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑q些直接依赖会引入什么传递依赖。但是有时候,当传递性依赖造成问题的时候,我们需要清楚的知道该传递性依赖是从哪条依赖\径引入的?/p>
例如A->B->C->X(1.0)、A->D->X(2.0)QX是A的传递性依赖,但是两条依赖路径上有两个版本的XQ那个X会被Maven解析使用呢?Maven依赖调解的第一原则是:路径最q者优先。依赖调解第一原则不能解决所有问题,比如QA->B->Y(1.0)、A->C->Y(2.0)QY(1.0)和YQ?.0Q的依赖路径长度是一LQ到底谁会解析?在Maven2.0.9开始,Maven定义了依赖调解的W二原则Q第一声明者优先?/p>