Maven 依賴中 scope 詳解
阿新 • • 發佈:2018-11-06
- Maven 的哲學思想是,約定優於配置(Convention Over Configuration),Maven 依賴中 scope 的預設值是compile
- Scope 指定了依賴(第三方jar包)的 作用範圍
- 作用範圍包括,所在專案的測試、編譯、執行、打包等生命週期
- 其中,編譯和執行還分為
- 測試程式碼的編譯和執行
- 非測試程式碼的編譯和執行
scope 分類
- test 測試範圍
- 測試範圍的依賴(第三方jar包),針對測試相關程式碼的編譯和執行,在通常程式碼的編譯和執行時都不需要,只有在有關測試的程式碼編譯和執行測試程式碼階段
- 案例說明
- 環境 IJ maven web project
- 前提:需知facade slf4j 只有在classpath 中發現底層日誌實現framework時才起作用
pom.xml
- 測試範圍的依賴(第三方jar包),針對測試相關程式碼的編譯和執行,在通常程式碼的編譯和執行時都不需要,只有在有關測試的程式碼編譯和執行測試程式碼階段
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <!--此處test,表明 junit jar包只能出現在 test 環境下的classpath, 即 只能在標記為 “TestSources Root的 資料夾下”被呼叫, 而在“標記為Sources Root 的資料夾下”找不到其中的類--> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> <!--此處test 是關鍵,表明底層日誌實現框架-也即該依賴在test 程式碼編譯、執行時才起作用--> <scope>test</scope> </dependency> </dependencies>
測試程式碼
- 測試方法之一,即是上面pom註釋,junit 類呼叫只能在TestSources Root 目錄下起作用
- 測試方法之二
Sources Root 目錄下
public class LogDemo { Logger logger = LoggerFactory.getLogger(LogDemoTest.class); public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(LogDemo.class); //不能找到底層日誌使系統,因為 該依賴 為 test 範圍 logger.info("log"); } } 輸出: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
TestSources Root 目錄下
public class LogDemoTest {
Logger logger = LoggerFactory.getLogger(LogDemoTest.class);
@Test
public void test() {
//能找到底層日誌實現系統
logger.info("junit test");
}
}
輸出:
[main] INFO log.learn.LogDemoTest - junit test
- compile 編譯範圍
- 依賴預設範圍,該依賴需要參與當前專案的編譯、測試、執行、打包
- 什麼叫參與當前專案的編譯???
- runtime 執行時範圍
- 表示依賴無需參與當前專案的編譯,但是後期的執行和測試需要參與,不參與編譯能執行成功嗎??
- 與 compile 相比,跳過編譯而已
- 比如,你可能在編譯的時候需要 JDBC API JAR,只有在 執行時才需要 JDBC
- 貌似是編譯時該包不參與,執行時參與?
- provided 表明該依賴已經提供,故只在未提供時才被使用
- 應用場景是你定義了一個Servlet,此刻得需要Servlet-api.jar 才能編譯成功,但是當你達成war 包時,你並不想將 Servlet-api.jar 包進去,因為Tomcat等容器會提供
- 跟compile 類似,說明JDK、容器或使用者會提供這個依賴,如Servlet.jar
- 這個依賴只作用在** 編譯和測試,該依賴會由系統元件提供,不需手動新增,只存在編譯、執行、測試階段,打包是不用包進去,打包階段做了exclude**動作
- 沒有傳遞性
- system
- 被依賴項不會從maven倉庫下載,而是從本地系統指定路徑下尋找,需要 systemPath 屬性
scope 的傳遞依賴
- A -> B -> C, 當前專案 A,A依賴於B,B依賴於C,知道B在 A中的scope,怎麼知道 C在 A 中的 scope
- 即,A需不需要 C的問題,本質由 C在B中的scope決定
- 當 C 在 B 中的scope 是test 或 provided 時,C 直接被丟棄,A不依賴C
- 否則 A 依賴 C,C的scope 繼承與B 的scope