如果它们来自我父级的其他子模块,我应该依赖 Maven 中的传递依赖项吗?

Should I rely on transitive dependencies in Maven if they come from other sub-module of my parent?

假设我们正在处理 mortgage 子模块,并且我们在模块代码中直接使用 Google Guava 类,但是对于guava 在同一父模块下的其他子模块中定义,我们只能通过对 "investment" 模块的传递依赖来访问 Guava 类:

banking-system (parent pom.xml)
|
|-- investment (pom.xml defines <dependency>guava</dependency>)
|
|-- mortgage (pom.xml defiens <dependency>investment</dependency>)

我们是否还应该在抵押pom.xml中为番石榴放一个<dependency>

我们的 pom.xml 的缺点看起来像重复,优点是:如果开发 "investment" 的人放弃番石榴,那么它不会阻止我们的抵押子模块成功构建。

如果是,那么<version>我们应该指定什么? (none + <dependencyManagement> 在父 pom 中?)

如果是,那么我们是否应该在某些模块中使用 <provided> 作用域?

注意:请记住,我是在特定情况下问的,当模块具有共同的父 pom(例如作为一个整体的应用程序)时。

也许这个结构不是最好的例子,想象一下:

banking-app
    banking-core (dep.on: guava, commons, spring)
    investment (dep.on: banking-core)
    mortgage (dep.on: banking-core)

使用@Component时还是Investment显式声明Spring,如果使用Guava的LoadedCache则声明Guava?

当一个模块使用第 3 方库时,该模块也应该在其 pom.xml 中明确依赖该库。想象一下,如果另一个项目应该使用 'mortgage' 模块,并且已经不依赖于 Guava,它将失败,例如当单元测试遇到涉及 Guava 的代码路径时。显式依赖还涵盖了重构 'investment' 模块以使其不再使用 Guava 的场景。您的 'investment' 模块应该不受其依赖项中的此类更改的影响。

明确列出您的直接依赖项始终是正确的。关于版本,最好将其保留在父 pom 的 dependencyManagement 部分,以便所有子项目继承该(相同)版本。

  1. ,申报部门。这不是重复!!!编译依赖项是可传递的不是 Maven 开发人员的意图,它是由 java 语言强制的。因为像 class-inheritance 这样的特性强制了这种行为。您已经提到的 "pro" 是重要的事实。 参见 the (*) note in the transitive-scope-table

  2. 是的,总是在你的反应堆父级中声明需要的第三方库版本与 dependencyManagement。在 运行 时间从不同的 lib 版本中发现错误是一件痛苦的事情。避免在大型反应器的子模块中声明第三方库的版本,始终在父级中使用 depMngs。

  3. ,我只会将"provided"用于运行时间提供的依赖项,在您的示例中tomcat/jboss/wildfly/.. 对于 servlet-api/cdi-api/ 这样的东西。但不适用于第三方图书馆。 尽可能晚地声明 "provided" 范围(即您的部署模块 war/ear),而不是在您的业务模块中。这使得编写测试更容易。 例如:

    • 投资(取决于guava scope:=provided
    • 抵押(要看投资,自己不需要guava)

-->抵押class路径不包含guava。 如果你为抵押贷款编写一个单元测试,其中 classes 涉及投资,它将不起作用 -> 你需要至少声明 guava with scope=test/runtime to 运行 这些测试.. .

we are directly using the Google Guava classes in module code, but the dependcy for the guava is defined in other sub-module under the same parent and we have access to Guava classes only by transitive dependency on "investment" module [...] Should we still put a to Guava in the mortgage pom.xml?

,你应该在你的模块中声明 Google Guava 依赖,而不是期望它作为传递依赖可用。即使它适用于当前版本,但在以后的直接依赖版本中可能不再如此。

如果你的代码依赖于一个模块,你的代码应该只直接依赖于这个模块的类,而不是这个模块的传递依赖。正如您提到的,无法保证 investment 模块将来会继续依赖于 Guava。您需要在父级的 pom.xml 或模块本身中指定此依赖关系,以确保它在不依赖传递依赖关系的情况下可用。这不是重复,你还能如何告诉 Maven 你的模块依赖于 Guava?

我没有看到任何情况下您需要在其他情况下尊重最低限度的最佳实践。

If yes, then what <version> shoudle we specify? (none + <dependencyManagement> in parent pom?)

Yes,在父模块中使用 <dependencyManagement> 并在没有版本的子模块中使用 <dependency> 是最好的:您将确保所有模块都使用您的依赖项的相同版本。由于您的模块作为一个整体是一个应用程序,因此它可能会更好,因为它可以避免各种问题,例如在类路径上出现相同依赖项的不同版本会造成严重破坏。

即使出于某种原因,您的某个模块使用相同的父模块需要我们的依赖项的不同版本,仍然可以使用 <version>.[=19= 覆盖该特定模块的版本]

If yes, should we use a scope in some module then?

可能不会,具有 compile 作用域的依赖是大多数打包方法的最佳选择。

但是您可能会遇到需要或更喜欢这样做的情况,例如,如果所述模块需要使用特定于运行时环境的版本,或者如果您的部署或打包模型以需要它的方式设计。鉴于您所暴露的情况,这两种情况都是可能的,尽管大多数时候没有必要。