Maven詳解(五)------ 坐標的概念以及依賴管理


  我們知道maven能幫我們管理jar包,那么它是怎么管理的呢?這篇博客我們來詳細介紹。

1、什么是坐標?

  ①、數學中的坐標

    在平面上,使用 X 、Y 兩個向量可以唯一的定位平面中的任何一個點

    在空間中,使用 X、Y、Z 三個向量可以唯一的定位空間中的任意一個點

 

  ②、Maven 中的坐標

    俗稱 gav:使用下面三個向量子倉庫中唯一定位一個 Maven 工程

    在項目中的 pom.xml 文件中,我們可以看到下面gav的定義:

    1、groupid:公司或組織域名倒序 

      <groupid>com.ys.maven</groupid>

    2、artifactid:模塊名,也是實際項目的名稱

      <artifactid>Maven_05</artifactid>
    3、version:當前項目的版本
      <version>0.0.1-SNAPSHOT</version>

    

  ③、Maven 坐標和倉庫,jar 包的關系

    什么是倉庫,后面我們會詳細講解,現在你只需要知道是Maven 用來存放 jar 包的地方。

    那么依照上面定義的 gav,我們執行 mvn -install 命令,會出現什么情況呢?

    首先進入到我們第二篇博客 Maven 的安裝配置 ,通過 settings.xml 文件配置的倉庫目錄。

      將我們上面配置的 gav 向量組合起來就是目錄:

      com/ys/maven/Maven_05/0.0.1-SNAPSHOT/Maven_05-0.0.1-SNAPSHOT.jar

       

    其次,我們觀察打出來的 jar 包:

      Maven_05-0.0.1-SNAPSHOT.jar

    也就是 artifactid-version.jar

 

 

 

2、什么是依賴? 

   什么是 依賴?相信有過一定開發經驗的人知道,每當我們需要使用某個框架時,比如 SpringMVC,那么我們需要導入相應的 jar 包,但是手動導入包的時候,往往會漏掉幾個 jar 包,那么在使用該框架的時候系統就會報錯。那么我們就說導入的包與未導入的包存在依賴關系。而使用 Maven,我們只需要在 pom.xml 文件中進行相應的配置,它就會幫助我們自動管理 jar 包之間的依賴關系。那么它是怎么管理的呢,接下來我們會詳細講解。

 

3、依賴的詳細配置

  我們以 Junit 為例,在 pom.xml 文件中進行詳細而完整的配置。 

<project>      
    <dependencies> 
        <dependency>
            <groupId>junit</groupId>      
            <artifactId>junit</artifactId>      
            <version>3.8.1</version>
            <type>...</type>
            <scope>...</scope>
            <optional>...</optional>
            <exclusions>      
                <exclusion>      
                  <groupId>...</groupId>      
                  <artifactId>...</artifactId>      
                </exclusion> 
          </exclusions>      
        </dependency>         
      </dependencies>      
</project>

  ①、dependencies:一個 pom.xml 文件中只能存在一個這樣的標簽。用來管理依賴的總標簽。

  ②、dependency:包含在dependencies標簽中,可以有無數個,每一個表示一個依賴

  ③、groupId,artifactId和version:依賴的基本坐標,對於任何一個依賴來說,基本坐標是最重要的,Maven根據坐標才能找到需要的依賴。

  ④、type:依賴的類型,對應於項目坐標定義的packaging。大部分情況下,該元素不必聲明,其默認值是jar。

  ⑤、scope:依賴的范圍,默認值是 compile。后面會進行詳解。

  ⑥、optional:標記依賴是否可選。

  ⑦、exclusions:用來排除傳遞性依賴,后面會進行詳細介紹。

  

 

4、依賴的范圍 scope 

   

  一般情況下,我們對前面三個依賴用的比較多。下面的主程序表示maven 目錄結構 src/main/java.測試程序目錄結構為:src/test/java

   1、compile 范圍依賴

    對主程序是否有效:有效

    對測試程序是否有效:有效

    是否參與打包:參與

    是否參與部署:參與

    典型例子:log4j

    

  2、test 范圍依賴

    對主程序是否有效:無效

    對測試程序是否有效:有效

    是否參與打包:不參與

    是否參與部署:不參與

    典型例子:Junit

  

  3、provided 范圍依賴

    對主程序是否有效:有效

    對測試程序是否有效:有效

    是否參與打包:不參與

    是否參與部署:不參與

    典型例子:servlet-api.jar,一般在發布到 服務器中,比如 tomcat,服務器會自帶 servlet-api.jar 包,所以provided 范圍依賴只在編譯測試有效。

    

   4、runtime 范圍依賴:在測試、運行的時候依賴,在編譯的時候不依賴。例如:JDBC驅動,項目代碼只需要jdk提供的jdbc接口,只有在執行測試和運行項目的時候才需要實現jdbc的功能。

   

   接下來我們舉幾個例子在工程中實際去理解:

    test 依賴和 compile 依賴的區別:

    ①、首先我們在 pom.xml 文件中配置,Junit 的 test 依賴

       

    ②、我們在主程序中去導入 Junit 的包,然后進行 mvn -compile 編譯,很明顯,test 范圍的在主程序中無效,故編譯會報錯。

      我們在 src/main/java 包下新建 MavenTest.java,並導入 Junit 包

      

      然后執行 mvn -compile 操作,如下圖報錯信息:

 

    ③、我們將 Junit 的依賴范圍改為 compile,然后執行 mvn -compile

      

      發現 mvn -compile 沒有報錯了。

      

 

 

4、依賴的傳遞

  比如我們創建三個Maven 工程,maven-first,maven-second以及maven-third,而third依賴於second,second又依賴於first,那么我們說 second 是 third 的第一直接依賴,first是second的第二直接依賴。而first是third的間接依賴。

  

 

   依賴之間的傳遞如下圖:第一列表示第一直接依賴,第一行表示第二直接依賴

  

  總結:

1、當第二依賴的范圍是compile的時候,傳遞性依賴的范圍與第一直接依賴的范圍一致。
2、當第二直接依賴的范圍是test的時候,依賴不會得以傳遞。
3、當第二依賴的范圍是provided的時候,只傳遞第一直接依賴范圍也為provided的依賴,且傳遞性依賴的范圍同樣為 provided;
4、當第二直接依賴的范圍是runtime的時候,傳遞性依賴的范圍與第一直接依賴的范圍一致,但compile例外,此時傳遞的依賴范圍為runtime;

  我們這里舉個例子來看:

  ①、第二依賴范圍是 test

    Maven_first 的pom.xml 文件如下:

    

    然后Maven_second依賴Maven_fisrt,Maven_third依賴Maven-second,其pom.xml 文件如下:

    Maven_second的 pom.xml

    

    

    Maven_third的 pom.xml

    

    我們發現在 Maven_third和 Maven_second 都沒有 Maven_first 引入的 Junit 包,正好符合上面總結的第二點:當第二直接依賴的范圍是test的時候,依賴不會得以傳遞。

     

     ②、第二依賴范圍是 compile

     如果我們將 Maven_first 的Junit 改為 compile,那么將會符合上面總結的第一點:當第二依賴的范圍是compile的時候,傳遞性依賴的范圍與第一直接依賴的范圍一致。

      

 

 

5、依賴的排除

  如果我們在當前工程中引入了一個依賴是 A,而 A 又依賴了 B,那么 Maven 會自動將 A 依賴的 B 引入當前工程,但是個別情況下 B 有可能是一個不穩定版,或對當前工程有不良影響。這時我們可以在引入 A 的時候將 B 排除。

  比如:我們在Maven_first 中添加 spring-core,maven 會自動將 commons-logging添加進來,那么由於 Maven_second 是依賴 Maven_first  的,那么 Maven_second  中將存在 spring-core(自帶了commons-logging),這時候我們不想要 commons-logging,那該怎么辦呢?我們上面第二大點提到了:

exclusions:用來排除傳遞性依賴

  Maven_first 的 pom.xml 文件

  由於 Maven_second 依賴 Maven_second,故Maven_second 存在 spring-core 包

  

 

   如何排除呢?我們在 Maven_second 的 pom.xml 文件中添加如下代碼:

  

  再次查看工程:Maven_second 的 commons-logging 已經移除了

  

 

6、依賴的沖突

  在maven中存在兩種沖突方式:一種是跨pom文件的沖突,一致是同一個pom文件中的沖突。

  ①、跨 pom 文件,路徑最短者優先。比如我們在 Maven_first 中的 Junit 是4.9版本的,Maven_second 中的 Junit 是4.8版本的,那么Maven_third 中的 Junit 將會是那個版本呢?

    

 

  由上圖我們可以看出,由於 Maven_second 是 Maven_third 的直接依賴,明顯相比於 Maven_first 路徑要短,所以 Maven_third 的 Junit 版本與 Maven_second 保持一致。

 

  ②、同一個pom.xml 文件,先申明者優先。

  

  

  看 Maven_second

  

 

7、可選依賴

  Optional標簽標示該依賴是否可選,默認是false。可以理解為,如果為true,則表示該依賴不會傳遞下去,如果為false,則會傳遞下去。

   

  我們是在 Maven_second 的 pom 文件中設定 Junit 不可傳遞,那么Maven_third 工程中將不會有來自 Maven_second 的 Junit 的傳遞。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM