Maven 会下载一个新的 SNAPSHOT jar 来替换刚刚在同一构建中创建的 jar 吗?
Would Maven download a new SNAPSHOT jar to replace a jar that just got created in the same build?
假设我们的构建是从 A 到 Z 构建模块。这些项目的 pom 文件中的所有 version 元素都设置为 -SNAPSHOT。
当我们构建pom文件时,maven从项目A开始,然后到B,最后到达项目Z。如果Z依赖于A,maven是否检查远程仓库是否有最新的A-SNAPSHOT.jar 并可能 替换刚刚在 A/target/ and/or 本地 Maven 存储库 中作为同一构建的一部分创建的 A-SNAPSHOT.jar?
我认为-o
可以避免上述情况,但我只是想了解。
是否可以将 -o
设置为特定的 groupId 以避免在上述情况下可能发生的模糊错误。
是否可以将构建配置为下载本地存储库中不可用的任何工件但不替换现有工件。
answer to another question 的一部分解决了您的问题:
When you build an application, Maven will search for dependencies in the local repository. If a stable version is not found there, it will search the remote repositories (defined in settings.xml or pom.xml) to retrieve this dependency. Then, it will copy it into the local repository, to make it available for the next builds.
For example, a foo-1.0.jar library is considered as a stable version, and if Maven finds it in the local repository, it will use this one for the current build.
Now, if you need a foo-1.0-SNAPSHOT.jar library, Maven will know that this version is not stable and is subject to changes. That's why Maven will try to find a newer version in the remote repositories, even if a version of this library is found on the local repository. However, this check is made only once per day. That means that if you have a foo-1.0-20110506.110000-1.jar (i.e. this library has been generated on 2011/05/06 at 11:00:00) in your local repository, and if you run the Maven build again the same day, Maven will not check the repositories for a newer version.
请注意,此每日检查是默认行为。可以使用 snapshot
元素内定义的 updatePolicy
元素自定义此行为。
updatePolicy
The frequency for downloading updates - can be
"always", "daily" (default), "interval:XXX" (in minutes) or "never"
(only if it doesn't exist locally).
感谢 Julien Carsique 的精确度。
据我了解,如果可用,会优先使用本地存储库中的 SNAPSHOTS 构建。
为了证明这一点,
- 将您的本地 Maven 存储库移至其他位置,将
.m2/repository
目录留空。 (不要删除它,因为您以后可能找不到某些工件。远程存储库确实会关闭 :))
- 更改 A 中被 Z
使用的 API
- 运行 构建。如果我的思路是正确的,那么在构建 Z 时 应该 失败。您没有更改远程工件,并且存储库中没有任何内容(因为您在上面的步骤中移动了它)。如果成功,则此(我的)答案是错误的。请发表评论and/or对我的答案投反对票,所以我也学习了。
- 如果需要,请恢复原始存储库文件夹
- 回滚 A 中的 API 更改。
希望对您有所帮助。
不,反应堆中的项目总是优先于其他依赖项。
即使在以下情况下也是如此:
- 运行 Maven 设置了
-U
标志,这意味着更新检查是强制的。
- 在
settings.xml
或 POM 中将 <updatePolicy>
设置为 always
。
- 将
install
插件配置为 <installAtEnd>true</installAtEnd>
Maven 会找出哪些工件是您的反应器的一部分,并将它们从更新检查中排除。
这很容易证明。如果您使用上述任一配置尝试 运行 Maven,您将看到 Maven 不会下载工件 A
(例如),因为每次下载都会记录在控制台中。
例如,假设您有这个根 POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>root</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>root</name>
<modules>
<module>A</module>
<module>B</module>
...
<module>Z</module>
</modules>
</project>
每个模块看起来像这样:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>root</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<name>...</name>
<artifactId>...</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
</project>
但最后一个看起来像这样:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>root</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>Z</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Z</name>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
那么不,模块 A 将永远不会被存储库中的工件的另一个版本替换。
确认Daniel回答,实现代码在Maven 2和3之间有很大变化,但基本上原理是这样的:
- 构建项目(模块)时,其工件附加到 "build reactor" 并标记为 "resolved"、
- 当项目需要工件时,它会在反应器中寻找已解决的工件,
- 如果未找到附加的已解决工件,那么它将请求查看本地和远程存储库的解决方案。
因为只有在没有找到已解决的工件并且模块构建正在将其工件附加到反应器时才进行解析,标记为已解决,那么答案是:不,Maven 不会下载新的 SNAPSHOT jar 来替换刚刚在同一构建中创建的 jar。
你可以看看下面的代码:MavenProject, DefaultArtifactResolver, DefaultArtifactResolver.
假设我们的构建是从 A 到 Z 构建模块。这些项目的 pom 文件中的所有 version 元素都设置为 -SNAPSHOT。
当我们构建pom文件时,maven从项目A开始,然后到B,最后到达项目Z。如果Z依赖于A,maven是否检查远程仓库是否有最新的A-SNAPSHOT.jar 并可能 替换刚刚在 A/target/ and/or 本地 Maven 存储库 中作为同一构建的一部分创建的 A-SNAPSHOT.jar?
我认为-o
可以避免上述情况,但我只是想了解。
是否可以将 -o
设置为特定的 groupId 以避免在上述情况下可能发生的模糊错误。
是否可以将构建配置为下载本地存储库中不可用的任何工件但不替换现有工件。
answer to another question 的一部分解决了您的问题:
When you build an application, Maven will search for dependencies in the local repository. If a stable version is not found there, it will search the remote repositories (defined in settings.xml or pom.xml) to retrieve this dependency. Then, it will copy it into the local repository, to make it available for the next builds.
For example, a foo-1.0.jar library is considered as a stable version, and if Maven finds it in the local repository, it will use this one for the current build.
Now, if you need a foo-1.0-SNAPSHOT.jar library, Maven will know that this version is not stable and is subject to changes. That's why Maven will try to find a newer version in the remote repositories, even if a version of this library is found on the local repository. However, this check is made only once per day. That means that if you have a foo-1.0-20110506.110000-1.jar (i.e. this library has been generated on 2011/05/06 at 11:00:00) in your local repository, and if you run the Maven build again the same day, Maven will not check the repositories for a newer version.
请注意,此每日检查是默认行为。可以使用 snapshot
元素内定义的 updatePolicy
元素自定义此行为。
updatePolicy
The frequency for downloading updates - can be "always", "daily" (default), "interval:XXX" (in minutes) or "never" (only if it doesn't exist locally).
感谢 Julien Carsique 的精确度。
据我了解,如果可用,会优先使用本地存储库中的 SNAPSHOTS 构建。 为了证明这一点,
- 将您的本地 Maven 存储库移至其他位置,将
.m2/repository
目录留空。 (不要删除它,因为您以后可能找不到某些工件。远程存储库确实会关闭 :)) - 更改 A 中被 Z 使用的 API
- 运行 构建。如果我的思路是正确的,那么在构建 Z 时 应该 失败。您没有更改远程工件,并且存储库中没有任何内容(因为您在上面的步骤中移动了它)。如果成功,则此(我的)答案是错误的。请发表评论and/or对我的答案投反对票,所以我也学习了。
- 如果需要,请恢复原始存储库文件夹
- 回滚 A 中的 API 更改。
希望对您有所帮助。
不,反应堆中的项目总是优先于其他依赖项。
即使在以下情况下也是如此:
- 运行 Maven 设置了
-U
标志,这意味着更新检查是强制的。 - 在
settings.xml
或 POM 中将<updatePolicy>
设置为always
。 - 将
install
插件配置为<installAtEnd>true</installAtEnd>
Maven 会找出哪些工件是您的反应器的一部分,并将它们从更新检查中排除。
这很容易证明。如果您使用上述任一配置尝试 运行 Maven,您将看到 Maven 不会下载工件 A
(例如),因为每次下载都会记录在控制台中。
例如,假设您有这个根 POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>root</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>root</name>
<modules>
<module>A</module>
<module>B</module>
...
<module>Z</module>
</modules>
</project>
每个模块看起来像这样:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>root</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<name>...</name>
<artifactId>...</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
</project>
但最后一个看起来像这样:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>root</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>Z</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Z</name>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
那么不,模块 A 将永远不会被存储库中的工件的另一个版本替换。
确认Daniel回答,实现代码在Maven 2和3之间有很大变化,但基本上原理是这样的:
- 构建项目(模块)时,其工件附加到 "build reactor" 并标记为 "resolved"、
- 当项目需要工件时,它会在反应器中寻找已解决的工件,
- 如果未找到附加的已解决工件,那么它将请求查看本地和远程存储库的解决方案。
因为只有在没有找到已解决的工件并且模块构建正在将其工件附加到反应器时才进行解析,标记为已解决,那么答案是:不,Maven 不会下载新的 SNAPSHOT jar 来替换刚刚在同一构建中创建的 jar。
你可以看看下面的代码:MavenProject, DefaultArtifactResolver, DefaultArtifactResolver.