小小白:maven父工程里的dependencies和dependencyManagement有啥区别?

小小白:maven父工程里的dependencies和dependencyManagement有啥区别?

小小白: 我今天尝试搭建SpringCloud工程的时候,建了一个cloudParent父工程,里面包含两个子工程:gateway和server1,gateway工程需要用到spring-cloud-gateway-core的依赖。我本身父工程pom的dependencies中是有spring-cloud-dependencies依赖的配置,但是没有放到dependencyManagement里面,然后gateway里就一直显示无法引用到。

小小白: 后来隔壁组的宁小胖来帮我把spring-cloud-dependencies的依赖丢到dependencyManagement里面就能引用到的。他给我解释说,dependencies和dependencyManagement的区别是:

父工程中dependencies使用场景是,各个子模块需要用到完全一样依赖的时候,把这部分定义在父工程的dependencies中。

父工程中dependencyManagement使用场景是 子模块的依赖是父模块的子集,并不完全一样的情况下把各子模块依赖的全集定义在父工程的dependencyManagement中。

白久: 宁小胖说的有点问题,我们要区分理解两个概念:一个是dependencies和dependencyManagement的区别、另一个是maven父子模块的继承关系。

dependencies和dependencyManagement的区别

maven官方dependencyManagement定义是这样的:

Default dependency information for projects that inherit from this one. The dependencies in this section are not immediately resolved.
  Instead, when a POM derived from this one declares a dependency described by a matching groupId and artifactId, the version and other values from this section are used for that dependency if they were not already specified.

案例:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.8.RELEASE</version>
            <scope>compile</scope>
        </dependency>
</dependencies>

maven官方dependencyManagement定义是这样的:

This element describes all of the dependencies associated with a project.
These dependencies are used to construct a classpath for your project during the build process. They are automatically downloaded from the  repositories defined in this project.
See &lt;a href=&quot;http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html&quot;&gt;the  dependency mechanism&lt;/a&gt; for more information.

案例:

<dependencyManagement>
    <dependencies>
          <dependency>
             <groupId>org.springframework</groupId>
              <artifactId>spring-core</artifactId>
              <version>5.2.8.RELEASE</version>
              <scope>compile</scope>
          </dependency>
    </dependencies>
</dependencyManagement>

小小白: 说人话,听不懂

白久: 呃,从字面理解,dependencies是依赖,dependencyManagement是依赖管理器;

dependencyManagement,一般是用来统一管理jar包的版本号,是一种声明我要依赖谁、依赖那个版本号,至于你具体又没有依赖,还是要看dependencies标签里面定义的那些jar包。

dependencies,一般是用来定义我们工程中具体要用哪些jar包,每个jar包信息使用dependency标签描述。

dependency中包含:groupId、artifactId、version和scope,其中groupId和artifactId必须要有,用来定位使用哪个具体的jar包的。version和scope则都可以省略不写,当scope标签没有设置的时候,默认是compile级别。 version标签的规则是:如果配置了则使用配置的值作为版本号,如果没有配置,则会从当前工程的dependencyManagement标签中查找是否有配置版本号,如果没有则会继续向父级工程的dependencyManagement中查找,如果找不到则会引入失败。


小小白:那maven父子模块继承和jar包依赖之间又有啥关系呢?

白久: maven通过在子工程pom文件中配置 parent标签,指定该子工程的父工程。同时也可以在父工程的pom文件中配置modules标签,指定该父工程的的下属子工程。parent标签和modules标签都是可以无限套娃下去的。父子模块之间可以继承很多配置标签,这边我给你说一下父子工程中的dependencies和dependencyManagement着两个标签的继承关系。

maven父子模块jar包依赖的继承关系

在父工程pom中定义的dependencies依赖会被所有子模块工程继承,也就是说一般情况下,我们一个项目中,如果所有模块子工程都要用到的jar包可以定义到父工程中,比如spring-core这些所有工程肯定用到的,只需要在父工程中定义和维护,不需要每个子模块都去定义。

同样父工程pom中定义的dependencyManagement依赖管理器也会被所有子模块工程继承,但是按照刚才和你解释的,依赖管理器一般只管理版本号,所以具体子模块依赖不依赖这个jar包还是要看子模块中dependencies的配置,按照这个思路,一般情况下,我们一个项目中,会将所有子工程中依赖的jar包的版本号全部定义到父工程dependencyManagement中,这样维护某个jar包的版本号也只需要在父工程中统一维护,如果某个子工程需要使用和别人不一样的jar包版本号,只需要在自己的pom中配置自己的版本号即可。

小小白: 我现在理解了

父工程中dependencyManagement使用场景是 子模块的依赖是父模块的子集,并不完全一样的情况下把各子模块依赖的全集定义在父工程的dependencyManagement中。

这句话的意思是 用来管理各模块依赖的版本号的,不是各模块的实际依赖哪些jar包。

小小白:我现在明白为什么我的SpringCloud工程子模块一直无法引用到依赖了

小小白: 父工程pom的dependencies中是有spring-cloud-dependencies依赖的配置,也设置了版本号。但是gateway子工程在自己的pom文件dependencies中也定义了spring-cloud-dependencies依赖,却没有设置版本号,导致gateway的依赖覆盖了父工程的依赖设置。 父工程带版本号的spring-cloud-dependencies依赖放到dependencyManagement里面,gateway子工程就可以引用到,是因为按照版本号version标签的规则,从父工程的dependencyManagement里面继承了版本号。

小小白:这些你是怎么知道的,我要用小本本记下笔记。

白久: 我使用了百度的力量:


小小白: 你话多也就算了,为啥写这么多字也不配图,看着不累么?

白久: 博客写的少,还第一次按这种风格写,有点紧张 //... image