# maven 依赖管理

# 1 依赖范围

    <dependency>
  		<groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
1
2
3
4
5
6

<scope></scope> :这个标签的意思就是当前插件依赖的范围 在开发中我们把第三方 jar 放入到 classpath 中,就能够调用第三方的类和方法。  maven 有 3 中 classpath 分别是  :

  1. 编译

  2. 测试

  3. 运行

  4. compile 默认的范围,编译测试运行都有效。

  5. provided 编译和测试时有效,最后是在运行的时候不会被加入。官方举了一个例子。比如在 JavaEE web 项目中我们需要使用 servlet 的 API,但是呢 Tomcat 中已经提供这个 jar,我们在编译和测试的时候需要使用这个 api,但是部署到 tomcat 的时候,如果还加入 servlet 构建就会产生冲突,这个时候就可以使用 provided。

  6. runtime 在测试和运行时有效。

  7. test 在测试时有效。

  8. system 与本机系统相关联,可移植性差。编译和测试时有效。

  9. import 导入的范围,它只在使用 dependencyManagement 中,表示从其他 pom 中导入 dependecy 的配置

# 2 依赖传递

假如有 Maven 项目 A,项目 B 依赖 A,项目 C 依赖 B。那么我们可以说 C 依赖 A。也就是说,依赖的关系为:C—>B—>A。     那么我们执行项目 C 时,会自动把 B、A 都下载导入到 C 项目的 jar 包文件夹中。     这就是依赖的传递性。

# 3 依赖传递的排除

如上,C—>B—>A。加入现在不想执行 C 时把 A 下载进来,那么我们可以用 <exclusions>标签。

<dependencies>
<dependency>
    <groupId>B</groupId>
    <artifactId>B</artifactId>
    <version>0.0.1</version>

     <exclusions>
        <exclusion>
          <!--被排除的依赖包坐标-->
          <groupId>A</groupId>
          <artifactId>A</artifactId>
          <version>0.0.1</version>
        </exclusion>
     </exclusions>
</dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4 依赖冲突与解决

  1. 依赖是使用 Maven 坐标来定位的,而 Maven 坐标主要由 GAV(groupId, artifactId, version)构成。如果两个相同的依赖包,如果 groupId, artifactId, version 不同,那么 maven 也认为这两个是不同的。
  2. 依赖会传递,A 依赖了 B,B 依赖了 C,那么 A 的依赖中就会出现 B 和 C。
  3. Maven 对同一个 groupId, artifactId 的冲突仲裁,不是以 version 越大越保留,而是依赖路径越短越优先,然后进行保留。
  4. 依赖的 scope 会影响依赖的影响范围。

把这两个 jar 分别放到 A、B 两个项目中。C—>A—>B

 <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
 </dependency>

<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.12</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11

依赖冲突:一个项目 A,通过不同依赖传递路径依赖于 X,若在不同路径下传递过来的 X 版本不同,那么 A 应该导入哪个版本的 X 包呢? 冲突解决方案:

1:如果依赖路径的长度不同,则“短路优先”:

A—>B—>C—>D—>E—>X(version 0.0.1) A—>F—>X(version 0.0.2) 则 A 依赖于 X(version 0.0.2)。

2:依赖路径长度相同情况下,则“先声明优先”:

A—>E—>X(version 0.0.1) A—>F—>X(version 0.0.2) 则在项目 A 的<depencies></depencies>中,E、F 那个在先则 A 依赖哪条路径的 X。