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大體就像下面這個樣子的:
有興趣的朋友能夠看一下這個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包的特色是:
- 沒有發佈,因此不能經過maven中央倉庫找到
- 是第三方的,因此不能使用本身的私服引入
- 只有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。