你真的弄清楚SpringBoot的依賴管理了嗎?

1. 簡介

最近在處理一個SpringBoot多模塊項目的時候遇到一個問題,一個pom中只能有一個parent。java

使用SpringBoot把SpringBoot設置爲parent以後,項目自己就不能作爲父項目添加子模塊module了。mysql

怎麼處理?使用dependencyManagement。spring

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

dependencyManagement爲何有效?sql

在SpringBoot中咱們常常使用依賴不帶版本爲何也能夠?api

2. dependencyManagement

dependencyManagement其實主要不是爲了解決繼承問題,而是爲了解決依賴版本混亂問題。服務器

dependencyManagement主要用於多模塊項目的父項目中。maven

它的原理是:ide

當maven發現dependencies中的某個dependency沒有設置版本號version,它就會從它的父項目開始,在它的祖先項目中查找dependencyManagement中配置的dependency,直到找到一個有版本號version的依賴,使用該version。spring-boot

從名字也能夠看出dependencyManagement不是爲了定義依賴,而是爲了管理可能的依賴。有點繞,說個結論,就是若是在子模塊中沒有使用dependencyManagement定義的依賴,這些依賴的jar包就最終不會被打在輸出的jar包中。測試

3. 爲何使用SpringBoot不少依賴能夠不用配置版本號

若是你看SpringBoot的pom就會發現它的父項目是:

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>

spring-boot-dependencies中基本啥都沒幹,就定義了默認的依賴和版本了。

spring-boot-dependencies的pom大體就像下面這個樣子的:

SpringBoot依賴管理

有興趣的朋友能夠看一下這個pom中定義了哪些依賴,及其使用的版本。

4. 依賴管理

像SpringBoot同樣,咱們在多模塊項目中也能夠這樣玩,首先找出多個模塊的共同依賴,而後把他上移到父模塊的dependencyManagement,像這樣:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>${guava.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

依賴上移以後,子模塊的pom中要移除這些依賴,不然會覆蓋定義在父項目中的dependencyManagement中的依賴。

dependencyManagement中的dependencies下的依賴不能直接被子模塊繼承,必須顯式申明。直接在dependencies下的依賴能夠被子項目繼承。

# 分析哪些依賴使用了可是沒有顯式定義,哪些依賴定義了沒有使用
mvn dependency:analyze

# 分析依賴層級關係
mvn dependency:tree

# 查看有效依賴
mvn help:effective-pom

5. scope

5.1 compile

默認的依賴範圍就是compile,沒有scope或者scope爲comile的依賴表示編譯、運行、測試的時候都須要這個依賴的jar包。

5.2 provided

表示環境已經提供了,因此打包的時候就不會將scope爲provided的依賴打到輸出的jar包中。

最典型的例子是servlet-api,由於這個依賴已經包含在像Tomcat這樣的Servlet服務器中了,因此打包的時候就不須要將這個依賴再打包到輸出jar包中了。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>

5.3 runtime

若是一個依賴的scope爲runtime,表示編譯的時候不能引用這個依賴的jar包。

還有編譯的時候不須要運行的時候須要的jar包?

SPI相關的都是。主要是讓面向接口變成,而不要直接去使用實現類,如使用java.sql.Driver,而不是com.mysql.cj.jdbc.Driver。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
    <scope>runtime</scope>
</dependency>

5.4 test

scope爲test的依賴表示,這個包只是在測試階段使用,打包的時候這些依賴不會打在輸出的jar包中。

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
</dependency>

5.5 system

system主要是爲了引入一些沒有經過maven發佈的私有的三方jar包。

這些jar包的特色是:

  1. 沒有發佈,因此不能經過maven中央倉庫找到
  2. 是第三方的,因此不能使用本身的私服引入
  3. 只有jar包

固然你能夠把這些jar包加在classpath中,可是對於maven項目來講很差管理。

這個時候,就能夠使用scope爲system的依賴了,只須要指定這些jar包在系統中的路徑就能夠了。

<dependency>
    <groupId>vip.mycollege</groupId>
    <artifactId>tools</artifactId>
    <version>1.0.0</version>
    <scope>system</scope>
    <systemPath>F:/lib/tools.jar</systemPath>
</dependency>

5.6 import

import只能在dependencyManagement的dependency,而且type爲pom的依賴中使用。

import主要是爲了將依賴管理和依賴定義分開。

例如SpringBoot的dependencyManagement中預約義不少依賴,因此就單獨弄了一個spring-boot-dependencies來管理這些依賴。

6. optional

optional是用於控制依賴傳遞的。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

optional設置爲true,這個依賴不會被傳遞,加入在A項目中添加了這個依賴,B項目依賴A,可是B項目不會依賴spring-boot-devtools。

相關文章
相關標籤/搜索