maven 依賴版本管理— dependencyManagement

在開發 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

  • spring-boot-starter-web
  • mysql-connector-java
  • mybatis-spring-boot-starter

這個項目雖然引用了三個依賴,但只有 mybatis-spring-boot-starter 這個依賴是寫了版本號的,其他兩個沒寫。spring

咱們知道導入一個依賴須要提供依賴的座標 (groupIdartifactIdversion)sql

參考 maven 座標apache

既然 spring-boot-starter-webmysql-connector-java 沒有提供 version,那麼應該沒法正確下載依賴纔對。bash

但實際狀況如圖 mybatis

spring-boot-starter-webmysql-connector-java 都能找到對應都版本,這是爲何。

parent

不知道你們注意到沒,該 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 的版本號就在裏面

是否是和上面看到的版本號同樣,都是8.0.17

spring-boot-dependencies.pom

下面是 spring-boot-dependencies-2.1.9.RELEASE.pom 中的部份內容

注意如下三個組件

  • properties
  • dependencyManagement
  • pluginManagement

其中 properties 定義了一系列的版本號,而且在 dependencyManagement 中使用了版本號。注意這個 dependencyManagement,它的下級是咱們最經常使用的 dependencies 組件

咱們知道 dependencies 組件是用來引入依賴的,那在外面包上一層 dependencyManagement 是什麼意思呢? 它的意思是,聲明 dependencies 中的依賴,但不引用!!! 那何時引用呢?當子項目中配置了一個 dependency ,而且這個 dependency沒寫版本號,且在 dependencyManagement 中聲明過 時才引用。

這就是爲何有的依賴包須要寫版本號,有的不須要寫。那些不須要寫版本號的依賴,其實在它的父pom的dependencyManagement中已經申明好了,並且不只申明瞭 version,有的還申明瞭 exclusions ,用於剔除某些衝突的依賴

pluginManagement

上面說了 dependencyplugin 也是同理。不信你回頭看案例的pom文件,它裏面就定義了一個 spring-boot-maven-plugin 的插件,也沒有寫版本號。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
複製代碼

它的版本號一樣是在父pom的 pluginManagement 中申明好的

dependencies 組件

dependencies 組件用於導入依賴,且全部 dependencies 裏的依賴都會被子項目繼承。

公共依賴版本管理

像 spring boot 這種大致量的框架,旗下子項目衆多,好比

  • spring-boot-starter-web
  • spring-boot-starter-amqp
  • spring-boot-starter-data-redis
  • ...

這些子項目也有各自的依賴,其中有些依賴是公共的,好比

spring-boot-starter-web-2.1.9.RELEASEspring-boot-starter-data-redis--2.1.9.RELEASE 的依賴結構以下

他們都依賴了 spring-boot-starter,既然都是都是 spring-boot 的子項目,而且版本號也同樣,那麼他們兩個依賴的 spring-boot-starter 的版本也應該要同樣,否則同時引用他們兩個就會出現依賴衝突!

如何保證全部子項目的公共依賴的版本一致呢,總不能在每一個子項目裏寫死吧,這樣手動去管理得累死。

因此 spring boot 將全部公共依賴抽離出來,放到 spring-boot-dependencies 中來管理。 全部的子項目都直接或間接繼承自 spring-boot-dependencies,這樣同一個版本的全部的子項目的公共依賴就都同樣了。

但這樣作帶來了一個問題,每一個子項目都繼承了全部都公共依賴,解決這件事情,就須要使用 maven 的 dependencyManagement 組件

dependencyManagement 組件

做用用來申明依賴,但不導入。

dependencies 組件用於導入依賴,注意二者區別

特性

  • 子項目不會繼承 dependencyManagement 組件中聲明的依賴。
  • 但若是子項目想導入某個父pom 中 dependencyManagement 中的依賴,只須要填寫 groupId 和 artifactId ,不須要填寫版本號,maven會自動去父pom 的 dependencyManagement 中找對應的 version,包括scope、exclusions等

使用 dependencyManagement 組件後,全部的子項目只須要在父pom 的 「公共依賴聲明池」 中挑選本身想要的依賴,而不用關心版本。這樣即不會繼承到不須要的依賴,又統一了依賴的版本

若是想統一調整全部子項目某個依賴的版本,只須要在父pom 裏更新。不須要修改任何一個子項目。

若是某個子項目不想使用公共的版本號,只須要在 dependency 中加上版本號,子項目就會使用自定義的版本號,不會繼承父類版本號。

spring boot 就是經過這樣來統一管理依賴版本的

基於這樣的特性, dependencyManagement 組件 通常用於統一管理子項目的公共依賴的版本

依賴版本的查找

Maven會沿着父子層次向上走,直到找到一個擁有 dependencyManagement 組件的項目,而後在其中查找,若是找到則返回申明的依賴,沒有繼續往下找。

dependencies 與 dependencyManagement 的區別

dependencies

  • 引入依賴
  • 即便子項目中不寫 dependencies ,子項目仍然會從父項目中繼承 dependencies 中的全部依賴項

dependencyManagement

  • 聲明依賴,並不引入依賴。
  • 子項目默認不會繼承父項目 dependencyManagement 中的依賴
  • 只有在子項目中寫了該依賴項,而且沒有指定具體版本,纔會從父項目中繼承(version、exclusions、scope等讀取自父pom)
  • 子項目若是指定了依賴的具體版本號,會優先使用子項目中指定版本,不會繼承父pom中申明的依賴
相關文章
相關標籤/搜索