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 ?为什么不在需要的模块中直接定义它呢?
用我自己的话来说,你的父项目帮助你提供了两种依赖:
implicit dependencies : all the dependencies defined in the <dependencies> section in your parent-project are inherited by all the child-projects
explicit dependencies : allows you to select, the dependencies to apply in your child-projects. Thus, you use the <dependencyManagement> section, to declare all the dependencies you are going to use in your different child-projects. The most important thing is that, in this section, you define a <version> so that you don't have to declare it again in your child-project.
在我看来,<dependencyManagement>(如果我错了请纠正我)只是通过帮助您集中依赖项的版本而有用。它就像一种辅助功能。
作为最佳实践,您的<dependencyManagement>必须在父项目中,其他项目将继承它。一个典型的例子是通过声明Spring父项目来创建Spring项目。
两者之间的区别最好体现在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元素的引用,还是作为独立的依赖元素,都将立即被解析(即安装到本地存储库并可用于类路径)。
在我看来,还有一件事没有被充分强调,那就是不想要的继承。
下面是一个增量的例子:
我在父母的遗言中声明:
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
</dependencies>
繁荣!我把它放在我的子A、子B和子C模块中:
由子poms继承的隐式
一个单独的地方来管理
不需要在child pooms中重新声明任何内容
如果我想,我仍然可以在子B中重新调用和覆盖到18.0版本。
但是,如果我最终在Child C中不需要番石榴,在未来的Child D和Child E模块中也不需要番石榴呢?
他们仍然会继承它,这是不希望的!
这就像Java的God Object代码一样,从类中继承了一些有用的部分,同时也继承了大量不需要的东西。
这就是<dependencyManagement>发挥作用的地方。当你把它添加到你的父pom,你所有的子模块停止看到它。因此,你被迫进入每个单独的模块,确实需要它,并再次声明它(子A和子B,但没有版本)。
显然,您不会为Child C这样做,因此您的模块仍然是精简的。