在开发 spring boot 项目时,你是否遇到过,有些依赖即便不写版本号也能下载到某一版本的依赖。java
好比下面这个案例mysql
pom文件web
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.wqlm</groupId>
<artifactId>boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
复制代码
能够看到 <dependencies>
下配置了三个依赖项redis
这个项目虽然引用了三个依赖,但只有 mybatis-spring-boot-starter 这个依赖是写了版本号的,其他两个没写。spring
咱们知道导入一个依赖须要提供依赖的坐标 (groupId、artifactId、version)sql
参考 maven 坐标apache
既然 spring-boot-starter-web 和 mysql-connector-java 没有提供 version,那么应该没法正确下载依赖才对。bash
但实际状况如图 mybatis
不知道你们注意到没,该 pom 是有 parent 的框架
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/>
</parent>
复制代码
也就是说该项目继承自 spring-boot-starter-parent 项目。具体继承了那些东西,咱们点进去及能够看到了
以下图 spring-boot-starter-parent 又继承自 spring-boot-dependencies
再点进去能够看到 spring-boot-dependencies 的pom文件以下
能够看到 spring-boot-dependencies 没有 parent, 说明它是顶级pom,其中 <properties>
内定义了不少版本号,mysql-connector-java 的版本号就在里面
下面是 spring-boot-dependencies-2.1.9.RELEASE.pom 中的部份内容
注意如下三个组件
其中 properties 定义了一系列的版本号,而且在 dependencyManagement 中使用了版本号。注意这个 dependencyManagement,它的下级是咱们最经常使用的 dependencies 组件
咱们知道 dependencies 组件是用来引入依赖的,那在外面包上一层 dependencyManagement 是什么意思呢? 它的意思是,声明 dependencies 中的依赖,但不引用!!! 那何时引用呢?当子项目中配置了一个 dependency ,而且这个 dependency没写版本号,且在 dependencyManagement 中声明过 时才引用。
这就是为何有的依赖包须要写版本号,有的不须要写。那些不须要写版本号的依赖,其实在它的父pom的dependencyManagement中已经申明好了,并且不只申明了 version,有的还申明了 exclusions ,用于剔除某些冲突的依赖
上面说了 dependency,plugin 也是同理。不信你回头看案例的pom文件,它里面就定义了一个 spring-boot-maven-plugin 的插件,也没有写版本号。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
复制代码
它的版本号一样是在父pom的 pluginManagement 中申明好的
dependencies 组件用于导入依赖,且全部 dependencies 里的依赖都会被子项目继承。
像 spring boot 这种大致量的框架,旗下子项目众多,好比
这些子项目也有各自的依赖,其中有些依赖是公共的,好比
spring-boot-starter-web-2.1.9.RELEASE 和 spring-boot-starter-data-redis--2.1.9.RELEASE 的依赖结构以下
如何保证全部子项目的公共依赖的版本一致呢,总不能在每一个子项目里写死吧,这样手动去管理得累死。
因此 spring boot 将全部公共依赖抽离出来,放到 spring-boot-dependencies 中来管理。 全部的子项目都直接或间接继承自 spring-boot-dependencies,这样同一个版本的全部的子项目的公共依赖就都同样了。
但这样作带来了一个问题,每一个子项目都继承了全部都公共依赖,解决这件事情,就须要使用 maven 的 dependencyManagement 组件
做用:用来申明依赖,但不导入。
dependencies 组件用于导入依赖,注意二者区别
特性
使用 dependencyManagement 组件后,全部的子项目只须要在父pom 的 “公共依赖声明池” 中挑选本身想要的依赖,而不用关心版本。这样即不会继承到不须要的依赖,又统一了依赖的版本
若是想统一调整全部子项目某个依赖的版本,只须要在父pom 里更新。不须要修改任何一个子项目。
若是某个子项目不想使用公共的版本号,只须要在 dependency 中加上版本号,子项目就会使用自定义的版本号,不会继承父类版本号。
spring boot 就是经过这样来统一管理依赖版本的
基于这样的特性, dependencyManagement 组件 通常用于统一管理子项目的公共依赖的版本
Maven会沿着父子层次向上走,直到找到一个拥有 dependencyManagement 组件的项目,而后在其中查找,若是找到则返回申明的依赖,没有继续往下找。
dependencies
dependencyManagement