Introduction to Maven Repositories - tenji/ks GitHub Wiki

Maven 仓库说明

何为 Maven 仓库

在 Maven 世界中,任何一个依赖、插件或者项目构建的输出,都可以成为构件(Components)。例如,依赖log4j-1.2.15.jar是一个构件,插件maven-compile-plugin-2.0.2.jar是一个构件。任何一个构件都有一组坐标唯一标识。

在一台工作站上,可能会有几十个 Maven 项目,所有项目都使用maven-compiler-plugin,这些项目中的大部分都用到了log4j,有一小部分用到了 Spring Framework,还有另外一小部分用到了 Strut2。在每个有需要的项目中都放置了一份重复的 log4j 或者 struts2 显然不是最好的解决方案,这样做不仅造成了磁盘空间的浪费,而且也难以统一管理,文件的复制等操作也会降低构建的速度。而实际情况是,在不使用 Maven 的那些项目中,我们往往就能发现命名为lib/的目录,各个项目lib/目录下的内容存在大量的重复。

得益于坐标机制,任何 Maven 项目使用任何一个构建的方式都是完全相同的。在此基础上,Maven 可以在某个位置统一存储所有 Maven 项目共享的构件,这个统一的位置就是仓库。实际的 Maven 项目将不再各自存储其依赖文件,它们只需要声明这些依赖的坐标,在需要的时候(例如,编译项目的时候需要将依赖加入到classpath中),Maven 会自动根据坐标找到仓库中的构件,并使用它们。

仓库的布局

任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中唯一存储路径,这便是 Maven 的仓库布局方式。例如,log4j:log4j:1.2.15这一依赖,其对应的仓库路径为log4j/log4j/1.2.15/log4j-1.2.15.jar,该路径与坐标的大致对应关系为groupId/artifactId/version/artifactId-version.packaging

仓库的分类

对于 Maven 来说,仓库只分为两类:本地仓库远程仓库。当 Maven 根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地存在此构件,则直接使用;如果本地仓库不存在此构件,或者需要查看是否有更新的构建版本,Maven 就会去远程仓库查找,发现需要的构建之后,下载到本地仓库再使用。如果本地仓库和远程仓库都没有需要的构建,Maven 就会报错。

中央仓库是 Maven 核心自带的远程仓库,它包含了绝大部分开源的构件。在默认配置下,当本地仓库没有 Maven 需要的构件的时候,它就会尝试从中央仓库下载。

私服是另外一种特殊的远程仓库

仓库解析依赖的机制

当本地仓库没有依赖构件的时候,Maven 会自动从远程仓库下载;当依赖版本为快照版本的时候,Maven 会自动找到最新的快照。这背后的依赖解析机制可以概括如下:

  1. 当依赖的范围是system的时候,Maven 直接从本地文件系统解析构件。(关于依赖范围,查看)
  2. 根据依赖坐标计算仓库路径后,尝试直接从本地仓库寻找构件,如果发现相应构件,则解析成功。
  3. 在本地仓库不存在相应构件的情况下,如果依赖的版本是显式的发布版本构件,如1.2/2.1-beta-1等,则遍历所有远程仓库,发现后,现在并解析使用。
  4. 如果依赖的版本是 RELEASE 或者 LATEST,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/maven-metadata.xml,将其与本地仓库的对应元数据合并后,计算出 RELEASE 或者 LATEST 的真实的值,然后基于这个真实的值检查本地和远程仓库,如步骤2)和3)
  5. 如果依赖的版本是 SNAPSHOT,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/maven-metadata.xml,将其与本地仓库对应元数据合并后,得到最新快照版本的值,然后基于该值检查本地仓库,或者从远程仓库下载。

镜像