dependencyManagement和dependencies之间的区别是什么?
我在Apache Maven网站上看过文档。
在dependencyManagement下定义的依赖项似乎可以在其子模块中使用,而无需指定版本。
例如:
父项目(Pro-par)在dependencyManagement下定义了一个依赖项:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8</version>
</dependency>
</dependencies>
</dependencyManagement>
然后在Pro-par的子函数中,我可以使用junit:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
但是,我想知道是否有必要在父pom中定义junit ?为什么不在需要的模块中直接定义它呢?
The documentation on the Maven site is horrible. What dependencyManagement does is simply move your dependency definitions (version, exclusions, etc) up to the parent pom, then in the child poms you just have to put the groupId and artifactId. That's it (except for parent pom chaining and the like, but that's not really complicated either - dependencyManagement wins out over dependencies at the parent level - but if have a question about that or imports, the Maven documentation is a little better).
After reading all of the 'a', 'b', 'c' garbage on the Maven site and getting confused, I re-wrote their example. So if you had 2 projects (proj1 and proj2) which share a common dependency (betaShared) you could move that dependency up to the parent pom. While you are at it, you can also move up any other dependencies (alpha and charlie) but only if it makes sense for your project. So for the situation outlined in the prior sentences, here is the solution with dependencyManagement in the parent pom:
<!-- ParentProj pom -->
<project>
<dependencyManagement>
<dependencies>
<dependency> <!-- not much benefit defining alpha here, as we only use in 1 child, so optional -->
<groupId>alpha</groupId>
<artifactId>alpha</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>zebra</groupId>
<artifactId>zebra</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>charlie</groupId> <!-- not much benefit defining charlie here, so optional -->
<artifactId>charlie</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency> <!-- defining betaShared here makes a lot of sense -->
<groupId>betaShared</groupId>
<artifactId>betaShared</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
<!-- Child Proj1 pom -->
<project>
<dependencies>
<dependency>
<groupId>alpha</groupId>
<artifactId>alpha</artifactId> <!-- jar type IS DEFAULT, so no need to specify in child projects -->
</dependency>
<dependency>
<groupId>betaShared</groupId>
<artifactId>betaShared</artifactId>
<type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
</dependency>
</dependencies>
</project>
<!-- Child Proj2 -->
<project>
<dependencies>
<dependency>
<groupId>charlie</groupId>
<artifactId>charlie</artifactId>
<type>war</type> <!-- This is not a jar dependency, so we must specify type. -->
</dependency>
<dependency>
<groupId>betaShared</groupId>
<artifactId>betaShared</artifactId>
<type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
</dependency>
</dependencies>
</project>
两者之间的区别最好体现在Maven网站文档中提供的dependencyManagement元素的必要且充分的定义中:
dependencyManagement
从此继承的项目的默认依赖项信息。此部分中的依赖项不会立即解析。相反,当从这个POM派生的POM声明了一个由匹配的groupId和artifactId描述的依赖项时,如果这个节中的版本和其他值尚未指定,则将用于该依赖项。”
[https://maven.apache.org/ref/3.6.1/maven-model/maven.html]
你可以在另一页阅读更多信息:
“. .匹配依赖引用到依赖管理节的最小信息集实际上是{groupId, artifactId, type, classifier}。在许多情况下,这些依赖关系将引用不带分类器的jar工件。这允许我们将标识集简写为{groupId, artifactId},因为类型字段的默认值是jar,默认分类器是null。[https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html]
Thus, all the sub-elements (scope, exclusions etc.,) of a dependency element--other than groupId, artifactId, type, classifier, not just version--are available for lockdown/default at the point (and thus inherited from there onward) you specify the dependency within a dependencyElement. If you’d specified a dependency with the type and classifier sub-elements (see the first-cited webpage to check all sub-elements) as not jar and not null respectively, you’d need {groupId, artifactId, classifier, type} to reference (resolve) that dependency at any point in an inheritance originating from the dependencyManagement element. Else, {groupId, artifactId} would suffice if you do not intend to override the defaults for classifier and type (jar and null respectively). So default is a good keyword in that definition; any sub-element(s) (other than groupId, artifactId, classifier and type, of course) explicitly assigned value(s) at the point you reference a dependency override the defaults in the dependencyManagement element.
因此,在dependencyManagement之外的任何依赖元素,无论是作为某个dependencyManagement元素的引用,还是作为独立的依赖元素,都将立即被解析(即安装到本地存储库并可用于类路径)。
我在这个问题上迟到了,但我认为它值得一个比公认的回答更清晰的回答(公认的回答是正确的,但没有强调实际重要的部分,这需要您自己推断)。
在父POM中,<dependencies>和<dependencyManagement>之间的主要区别是:
Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s).
Artifacts specified in the <dependencyManagement> section, will only be included in the child module if they were also specified in the <dependencies> section of the child module itself. Why is it good you ask? Because you specify the version and/or scope in the parent, and you can leave them out when specifying the dependencies in the child POM. This can help you use unified versions for dependencies for child modules, without specifying the version in each child module.