依赖管理

Maven 中的依赖管理

依赖管理是 Maven 的一大特征,对于一个简单的项目,对依赖的管理并不是什么困难的事,但是如果这个项目依赖的库文件达到几十个甚至于上百个的时候就不是一个简单的问题了。在这个时候 Maven 对于依赖管理的作用就显露出来了。下面主要讨论几个方面的内容:传递性依赖,依赖范围,依赖管理,系统依赖,可选依赖

Maven 使用 dependencyManagement 元素来提供了一种管理依赖版本号的方式。通常会在一个组织或者项目的最顶层的父 POM 中看到 dependencyManagement 元素。使用 pom.xml 中的 dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有 dependencyManagement 元素的项目,然后它就会使用在这个 dependencyManagement 元素中指定的版本号。

例如在父项目里:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.2</version>
    </dependency>
    ...
  <dependencies>
</dependencyManagement>

然后在子项目里就可以添加 mysql-connector 时可以不指定版本号,例如:

<dependencies>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
</dependencies>

同时在 dependenceManagement 种,也可以从外部导入 POM 文件中的依赖项:

<dependencyManagement>
     <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.3.0.RC1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Dependency Scope

Maven 有三套 classpath(编译 classpath,运行 classpath,测试 classpath)分别对应构建的三个阶段。依赖范围就是控制依赖与这三套 classpath 的关系。依赖范围有六种。在 POM 4 中,<dependency> 中还引入了 <scope>,它主要管理依赖的部署。目前 <scope> 可以使用 5 个值:

  • compile,缺省值,适用于所有阶段,会随着项目一起发布。compile 是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的 classpath 中可用,同时它们也会被打包。

  • provided,provided 依赖只有在当 JDK 或者一个容器已提供该依赖之后才使用。例如,如果你开发了一个 web 应用,你可能在编译 classpath 中需要可用的 ServletAPI 来编译一个 servlet,但是你不会想要在打包好的 WAR 中包含这个 ServletAPI;这个 Servlet API JAR 由你的应用服务器或者 servlet 容器提供。已提供范围的依赖在编译 classpath(不是运行时)可用。它们不是传递性的,也不会被打包。

  • runtime,runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要 JDBC API JAR,而只有在运行的时候才需要 JDBC 驱动实现。

  • test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。

  • system,system 范围依赖与 provided 类似,但是你必须显式的提供一个对于本地系统中 JAR 文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven 也不会在仓库中去寻找它。如果你将一个依赖范围设置成系统范围,你必须同时提供一个 systemPath 元素。注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的 Maven 仓库中引用依赖)。

<project>
  ...
  <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>
  ...
</project>

使用 system 依赖范围

在下文中会有对于依赖的 scope 的详细解释,这里只需要知道如果将 scope 设置为了 system 即是自动在本地路径中寻找依赖的 Jar 包即可。

<dependency>
  <groupId>dnsns</groupId>
  <artifactId>dnsns</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/lib/dnsns.jar</systemPath>
</dependency>
<dependency>
  <groupId>localedata</groupId>
  <artifactId>localedata</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/lib/localedata.jar</systemPath>
</dependency>
<dependency>
  <groupId>sunjce_provider</groupId>
  <artifactId>sunjce_provider</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/lib/sunjce_provider.jar</systemPath>
</dependency>
<dependency>
  <groupId>sunpkcs11</groupId>
  <artifactId>sunpkcs11</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/lib/sunpkcs11.jar</systemPath>
</dependency>

maven-install-plugin

maven-install-plugin 默认绑定在 maven 的生命周期 install 阶段。该插件有三个 goals:

  • install:install 即默认的 maven install 执行的命令,用来自动地将本项目的主 artifact 以及它的附件如 source,doc 安装到本地的仓库中。

  • install:install-file 作为 install 的补充,安装你指定的文件到本地仓库。

  • install:help 本插件的帮助信息。

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>**</version>
上一页