java 在 <dependencyManagement> 部分声明依赖关系,即使没有在任何地方使用依赖?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/921599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Declare dependency in <dependencyManagement> section even if dependency not used everywhere?
提问by Mike Pone
We're using maven 2.1.0. I have multiple modules that are completely separate, but still have many common dependencies. Like log4J, but some modules don't need it. I am wondering if it is a good idea to declare all common dependencies in one parent file in the <dependencyManagement>section or is there a better way to deal with this?
我们正在使用 Maven 2.1.0。我有多个完全独立的模块,但仍然有许多共同的依赖项。像 log4J,但有些模块不需要它。我想知道在该<dependencyManagement>部分的一个父文件中声明所有常见依赖项是否是个好主意,或者是否有更好的方法来处理这个问题?
A follow up question about <dependencyManagement>. If I declare Log4J in the <dependencyManagement>section of the parent and a sub project does not use it, will it be included anyway?
关于<dependencyManagement>. 如果我<dependencyManagement>在父部分声明 Log4J并且子项目不使用它,它会被包含在内吗?
采纳答案by Kris
Each module should have its own POM and where it declares its own dependencies. This not only tracks external dependencies, but also internal ones.
每个模块都应该有自己的 POM 并在其中声明自己的依赖项。这不仅跟踪外部依赖项,还跟踪内部依赖项。
When you use Maven to build a project it will sort the whole lot out. So if many modules (perhaps all) depend on log4j, then it will only be included once. There are some problems if your modules depend on different versions of log4j but this approach usually works fine.
当您使用 Maven 构建项目时,它会将整个项目进行分类。因此,如果许多模块(可能全部)依赖于 log4j,那么它只会被包含一次。如果您的模块依赖于不同版本的 log4j,则会出现一些问题,但这种方法通常可以正常工作。
It is also useful (if there are more than 1-2 developers working together) to set up an internal repository (like Artifactory) and use that internally. It makes it much easier to deal with libraries that are not in the public repos (just add it to your internal repo!) and you can also use build tools to push builds of your own code there so other can use the modules without checking out the code (useful in larger projects)
设置内部存储库(如Artifactory)并在内部使用它也很有用(如果有超过 1-2 个开发人员一起工作)。它可以更轻松地处理不在公共存储库中的库(只需将其添加到您的内部存储库中!)并且您还可以使用构建工具将您自己的代码的构建推送到那里,以便其他人可以使用这些模块而无需检查代码(在大型项目中有用)
回答by Rich Seller
If you have a parent project, you can declare all dependencies and their versions in the dependencyManagement section of the parent pom. This doesn'tmean that all projects will use all those dependencies, it means that if a project does declare the dependency, it will inherit the configuration, so it only need declare the groupId and artifactId of the dependency. You can even declare your child projects in the parent's dependencyManagement without introducing a cycle.
如果您有父项目,则可以在父 pom 的 dependencyManagement 部分声明所有依赖项及其版本。这并不意味着所有项目都会使用所有这些依赖项,这意味着如果一个项目确实声明了依赖项,它将继承配置,因此只需要声明依赖项的 groupId 和 artifactId 即可。您甚至可以在不引入循环的情况下在父项的依赖项管理中声明您的子项目。
Note you can also do similar with plugins by declaring them in the pluginManagement section. This means any child declaring the plugin will inherit the configuration.
请注意,您还可以通过在 pluginManagement 部分中声明插件来对插件执行类似操作。这意味着任何声明插件的子项都将继承配置。
For example, if you have 4 projects, parent, core, uiand utils, you could declare all the external dependences and the internal project versions in the parent. The child projects then inherit that configuration for any dependencies they declare. If all modules are to have the same version, these can be even be declared as properties in the parent.
例如,如果您有 4 个项目,parent、core、ui和utils,则可以在 parent 中声明所有外部依赖项和内部项目版本。然后子项目为它们声明的任何依赖项继承该配置。如果所有模块都具有相同的版本,它们甚至可以在父级中声明为属性。
An example parent is as follows:
一个示例父如下:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>ui</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>utils</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>utils</module>
<module>core</module>
<module>ui</module>
</modules>
</project>
And the utils, core, and ui projects inherit all the relevant versions. utils:
并且 utils、core 和 ui 项目继承了所有相关版本。用途:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>utils</artifactId>
<!--note version not declared as it is inherited-->
<parent>
<artifactId>parent</artifactId>
<groupId>name.seller.rich</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
</project>
core:
核:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
<parent>
<artifactId>parent</artifactId>
<groupId>name.seller.rich</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>utils</artifactId>
</dependency>
</dependencies>
ui:
用户界面:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>ui</artifactId>
<parent>
<artifactId>parent</artifactId>
<groupId>name.seller.rich</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
</project>
回答by Craig P. Motlin
I wrote up a list of best practices. Here are the most important ones.
我写了一份最佳实践清单。这里是最重要的。
- Always use the maven-enforcer-plugin
- Enforce dependency convergence
- Otherwise it's possible that you depend on two different jars which both depend on log4j. Which one gets used at compile time depends on a set of rules that you shouldn't have to remember. They can both (!) get exported as transitive dependencies.
- Require plugin versions(for all plugins, even the built in ones)
- Define them in pluginManagement in the parent pom to define versions
- Otherwise a new version of maven-surefire-plugin could break your build
- Enforce dependency convergence
- Use dependencyManagement in the parent pom to use versions consistently across all modules
- Periodically run mvn dependency:analyze
- It's possible that you're getting a dependency transitively that you directly depend on at compile time. If so, it's important to add it to your pom with the version you require. This plays nicely with the enforcer plugin.
- It's possible that you're declaring extra dependencies that you don't use. This doesn't work properly 100% of the time, especially with libraries that are designed to have optional pieces (i.e. slf4j-api gets detected properly, but slf4j-log4j12 fails).
- 始终使用maven-enforcer-plugin
- 在父 pom 中使用 dependencyManagement 以在所有模块中一致地使用版本
- 定期运行mvn dependency:analyze
- 您可能会获得一个在编译时直接依赖的依赖项。如果是这样,重要的是将它添加到您需要的版本的 pom 中。这与执行器插件很好地配合。
- 您可能声明了不使用的额外依赖项。这在 100% 的情况下都不能正常工作,尤其是对于设计为具有可选部分的库(即 slf4j-api 被正确检测到,但 slf4j-log4j12 失败)。
回答by DavidValeri
A follow up question about . If I declare Log4J in the section of the parent and a sub project does not use it, will it be included anyway?
关于 . 如果我在父部分声明 Log4J 并且子项目不使用它,它会被包含在内吗?
No. Dependency management only sets the default version and possibly scope (I've seen this both appear to be inherited and appear to not be inherited so you will need to look this one up on your own). To include the dependency in a child module, you need to declare it as a dependency of the module and omit the version element. You can override the default in a child module simply be including the version number in the dependency element of the child module's POM.
不。依赖管理只设置默认版本和可能的范围(我已经看到这两者似乎是继承的,似乎不是继承的,所以你需要自己查找这个)。要在子模块中包含依赖项,您需要将其声明为模块的依赖项并省略 version 元素。您可以覆盖子模块中的默认值,只需在子模块的 POM 的依赖项元素中包含版本号。
I have multiple modules that are completely separate, but still have many common dependancies.
我有多个完全独立的模块,但仍然有许多共同的依赖项。
In this case, yes and no.
在这种情况下,是和否。
For modules that are built, versioned, and deployed together as a unified project, for instance the modules that compose a single Web application, most definitely yes. You want to relieve yourself of the headache of changing the version in more than one POM when you decide to move to a new version of a dependency. It can also save you work when you need to exclude certain transitive dependencies. If you declare the dependency with its excludes in the section you don't have to maintain the exclusions in multiple POMs.
对于作为统一项目一起构建、版本化和部署的模块,例如组成单个 Web 应用程序的模块,绝对可以。当您决定移动到依赖项的新版本时,您希望摆脱在多个 POM 中更改版本的麻烦。当您需要排除某些传递依赖项时,它还可以节省您的工作。如果您在该部分中使用排除项声明依赖项,则不必在多个 POM 中维护排除项。
For modules that are not directly related but are built within a single team within the company you may want to consider declaring default versions for common libraries like testing utilities, logging utilities, etc. in order to keep the team working with the standard versions of the tools that you have defined as part of your best practices. Remember you can always increase the version of your super POM when you standardize on a new set of common libraries. Where you draw the line between standardized library and tools and project specific libraries and tools is up to you but it should be easy for your team to find.
对于不直接相关但在公司内的单个团队中构建的模块,您可能需要考虑为公共库(如测试实用程序、日志实用程序等)声明默认版本,以保持团队使用标准版本的您已定义为最佳实践一部分的工具。请记住,当您标准化一组新的公共库时,您始终可以增加超级 POM 的版本。标准化库和工具与项目特定库和工具之间的界线由您决定,但您的团队应该很容易找到。
回答by Dwight Shih
We use a single common parent with a dependencyManagement block for all our projects. This is starting to break down as we move more projects into maven - if a project needs a different version then we have to either declare it as a dependency for all children or explicitly define the version for each pertinent child.
我们为所有项目使用一个带有dependencyManagement 块的公共父级。随着我们将更多项目移入 maven,这开始崩溃——如果一个项目需要不同的版本,那么我们必须要么将其声明为所有子项的依赖项,要么为每个相关子项明确定义版本。
We're trying out a model where we split the dependencyManagement out from our common parent and then import our corporate dependencyManagement pom into the top level project pom. This allows us to selectively define project defaults that override the corporate defaults.
我们正在尝试一种模型,将dependencyManagement 从我们的共同父项中分离出来,然后将我们的公司dependencyManagement pom 导入到顶级项目pom 中。这允许我们有选择地定义覆盖公司默认值的项目默认值。
Here is the original scenario:
这是原始场景:
A defines version 1.0 of foo.jar as the corporate default
B child of A
C1, C2, C3 children of B
D1, D2, D3 children of C1, C2, C3 respectively
If D1 and D2 require version 1.1 of foo.jar, then our choice used to be:
如果 D1 和 D2 需要 foo.jar 的 1.1 版本,那么我们以前的选择是:
- Declare foo.jar version 1.1 as a dependency in B, making it appear that C1, C2, C3 and D3 also depended upon version 1.1
- Declare foo.jar version 1.1 as a dependency in D1 and D2, moving the dependency declaration into multiple places deeper in our project hierarchy.
- 将 foo.jar 1.1 版声明为 B 中的依赖项,使 C1、C2、C3 和 D3 看起来也依赖于 1.1 版
- 将 foo.jar 版本 1.1 声明为 D1 和 D2 中的依赖项,将依赖项声明移动到我们项目层次结构中更深的多个位置。
Here is what we're trying out:
这是我们正在尝试的内容:
A defines version 1.0 of foo.jar as the corporate default
B dependencyManagement: imports A, declares a default of foo.jar version 1.1
C1, C2, C3 children of B
D1, D2, D3 children of C1, C2, C3 respectively
Now D1 and D2 just declare a dependency upon foo.jar and pick up version 1.1 from the dependencyManagement block of B.
现在 D1 和 D2 只是声明了对 foo.jar 的依赖,并从 B 的依赖管理块中选择了 1.1 版。
回答by MikeJ
In a multi-module project I place any common dependencies in the element of the parent pom.xml. I'm not sure if this would be best practice if the modules were not related to the same project though.
在多模块项目中,我将所有常见的依赖项放在父 pom.xml 的元素中。如果模块与同一个项目无关,我不确定这是否是最佳实践。

