Maven最佳實踐:管理依賴
有人認為Maven是一個依賴管理工具,當然這種想法是錯誤的(確切的說Maven是一個專案管理工具,貫穿了整個專案生命週期,編譯,測試,打包,釋出...),但Maven給人造成這種錯誤的印象也是有原因的,因為Maven的依賴管理十分強大,用好了Maven,你不再需要面對一大堆jar 感到頭大,依賴衝突,無用依賴等問題也能夠得到有效的防止和解決。本節介紹如何用好Maven的依賴管理。
最簡單的依賴
依賴是使用Maven座標來定位的,而Maven座標主要由GAV(groupId, artifactId, version)構成。因此,使用任何一個依賴之間,你都需要知道它的Maven座標,關於如何尋找Maven座標,《搜尋Maven倉庫》一文可以幫助你。
最簡單的依賴如:
Xml程式碼
junit
junit
4.4
上例中我們宣告瞭一個對junit的依賴,它的groupId是junit, artifactId是junit, version是4.4。這一組GAV構成了一個Maven座標,基於此,Maven就能在本地或者遠端倉庫中找到對應的junit-4.4.jar檔案。
依賴歸類
隨著專案的增大,你的依賴越來越多,比如說你依賴了一堆spring的jar,有 org.spring.framework:spring-core, org.spring.framework:beans, org.spring.framework:spring-web, org.spring.framework:spring-mock。它們的groupId是相同的,artifactId不同。為了管理其版本,你對它們進行過統一的升級,逐個的將version改成了最新版。但是,顯然,當POM很大的時候你說不定會犯錯誤,而當版本不一致的時候,一些詭異的相容性問題就可能出現。
對此,Maven有它的解決方案:
Xml程式碼
org.spring.framework
spring-core
${spring.version}
org.spring.framework
spring-beans
${spring.version}
org.spring.framework
spring-web
${spring.version}
org.spring.framework
spring-mock
${spring.version}
2.5
這裡我們定義了一個Maven屬性,其名稱為spring.version,值是2.5。在這個POM中,我們就能用${spring.version}的方式來引用該屬性。我們看到,所有spring相關的依賴的version元素現在都成了${spring.version},當Maven執行的時候,它會自動用值2.5來替換這個引用。
當我們需要升級spring的時候,只要更改一個地方便可,而且,你現在能很高的保證所有的spring依賴包都是同一個版本。
依賴範圍(scope)
本文的第一個例子其實是有漏洞的,對於Junit,一般來說你只有在執行測試的時候需要它,也就是說,它對於src/main/java的classpath沒什麼意義,並且,將Junit的jar檔案打入最終的釋出包也不是好事,這無謂的增加了釋出包的大小。
其實我們應該這樣做:
Xml程式碼
junit
junit
4.4
test
於是,junit對於主原始碼classpath不可用,對於測試原始碼classpath可用,不會被打包。
再舉個例子,在開發javaee應用的時候我們一定會用到servlet-api,它對於主原始碼和測試原始碼都是必要的,因為我們的程式碼中會引入 servlet-api的包。但是,在打包的時候,將其放入WAR包就會有問題,因為web容器會提供servlet-api,如果我們再將其打包就會造成依賴衝突,解決方案如下:
Xml程式碼
javax.servlet
servlet-api
2.4
provided
將依賴範圍設定成provided,就意味著該依賴對於主原始碼classpath,以及測試classpath可用,但不會被打包。這正是servlet-api所需要的。
這裡歸納一下主要的依賴範圍以及作用:
需要注意的是,當我們沒有宣告依賴範圍的時候,其預設的依賴範圍是compile。
分類器(classifer)
GAV是Maven座標最基本最重要的組成部分,但GAV不是全部。還有一個元素叫做分類器(classifier),90%的情況你不會用到它,但有些時候,分類器非常不可或缺。
舉個簡單的例子,當我們需要依賴TestNG的時候,簡單的宣告GAV會出錯,因為TestNG強制需要你提供分類器,以區別jdk14和jdk15,我們需要這樣宣告對TestNG的依賴:
Xml程式碼
org.testng
testng
5.7
jdk15
你會注意到maven下載了一個名為testng-5.7-jdk15.jar的檔案。其命名模式實際上是--.。理解了這個模式以後,你就會發現很多檔案其實都是預設構件的分類器擴充套件,如 myapp-1.0-test.jar, myapp-1.0-sources.jar。
分類器還有一個非常有用的用途是:我們可以用它來宣告對test構件的依賴,比如,我們在一個核心模組的src/test/java中宣告瞭一些基礎類,然後我們發現這些測試基礎類對於很多其它模組的測試類都有用。沒有分類器,我們是沒有辦法去依賴src/test/java中的內容的,因為這些內容不會被打包到主構件中,它們單獨的被打包成一個模式為--test.jar的檔案。
我們可以使用分類器來依賴這樣的test構件:
Xml程式碼
org.myorg.myapp
core
${project.version}
test
理解了分類器,那麼可供依賴的資源就變得更加豐富。
依賴管理(dependencyManagement)
當你只有一個Maven模組的時候,你完全不需要看這個部分。但你心裡應該清楚,只有一個Maven模組的專案基本上只是個玩具。
實際的專案中,你會有一大把的Maven模組,而且你往往發現這些模組有很多依賴是完全專案的,A模組有個對spring的依賴,B模組也有,它們的依賴配置一模一樣,同樣的groupId, artifactId, version,或者還有exclusions, classifer。細心的分會發現這是一種重複,重複就意味著潛在的問題,Maven提供的dependencyManagement就是用來消除這種重複的。
正確的做法是:
1. 在父模組中使用dependencyManagement配置依賴
2. 在子模組中使用dependencies新增依賴
dependencyManagement實際上不會真正引入任何依賴,dependencies才會。但是,當父模組中配置了某個依賴之後,子模組只需使用簡單groupId和artifactId就能自動繼承相應的父模組依賴配置。
這裡是一個來自於《Maven權威指南》的例子:
父模組中如此宣告:
Xml程式碼
4.0.0
org.sonatype.mavenbook
a-parent
1.0.0
...
mysql
mysql-connector-java
5.1.2
...
子模組中如此宣告:
4.0.0
org.sonatype.mavenbook
a-parent
1.0.0
project-a
...
mysql
mysql-connector-java
你依賴配置越複雜,依賴管理所起到的作用就越大,它不僅能夠幫助你簡化配置,它還能夠幫你鞏固依賴配置,也就是說,在整個專案中,對於某個構件(如mysql)的依賴配置只有一種,這樣就能避免引入不同版本的依賴,避免依賴衝突。
小結
本文講述了一些Maven依賴中重要的概念,並透過樣例提供了一些最佳實踐,如依賴歸類,依賴範圍,分類器,以及依賴管理。我的目的是透過淺顯的例子講述那些你實際工作中會需要了解的80%的內容,如果你需要更深入的瞭解,請參考《Maven權威指南》 。[@more@]http://tech.it168.com/a2009/0224/266/000000266570.shtml
最簡單的依賴
依賴是使用Maven座標來定位的,而Maven座標主要由GAV(groupId, artifactId, version)構成。因此,使用任何一個依賴之間,你都需要知道它的Maven座標,關於如何尋找Maven座標,《搜尋Maven倉庫》一文可以幫助你。
最簡單的依賴如:
Xml程式碼
上例中我們宣告瞭一個對junit的依賴,它的groupId是junit, artifactId是junit, version是4.4。這一組GAV構成了一個Maven座標,基於此,Maven就能在本地或者遠端倉庫中找到對應的junit-4.4.jar檔案。
依賴歸類
隨著專案的增大,你的依賴越來越多,比如說你依賴了一堆spring的jar,有 org.spring.framework:spring-core, org.spring.framework:beans, org.spring.framework:spring-web, org.spring.framework:spring-mock。它們的groupId是相同的,artifactId不同。為了管理其版本,你對它們進行過統一的升級,逐個的將version改成了最新版。但是,顯然,當POM很大的時候你說不定會犯錯誤,而當版本不一致的時候,一些詭異的相容性問題就可能出現。
對此,Maven有它的解決方案:
Xml程式碼
這裡我們定義了一個Maven屬性,其名稱為spring.version,值是2.5。在這個POM中,我們就能用${spring.version}的方式來引用該屬性。我們看到,所有spring相關的依賴的version元素現在都成了${spring.version},當Maven執行的時候,它會自動用值2.5來替換這個引用。
當我們需要升級spring的時候,只要更改一個地方便可,而且,你現在能很高的保證所有的spring依賴包都是同一個版本。
依賴範圍(scope)
本文的第一個例子其實是有漏洞的,對於Junit,一般來說你只有在執行測試的時候需要它,也就是說,它對於src/main/java的classpath沒什麼意義,並且,將Junit的jar檔案打入最終的釋出包也不是好事,這無謂的增加了釋出包的大小。
其實我們應該這樣做:
Xml程式碼
於是,junit對於主原始碼classpath不可用,對於測試原始碼classpath可用,不會被打包。
再舉個例子,在開發javaee應用的時候我們一定會用到servlet-api,它對於主原始碼和測試原始碼都是必要的,因為我們的程式碼中會引入 servlet-api的包。但是,在打包的時候,將其放入WAR包就會有問題,因為web容器會提供servlet-api,如果我們再將其打包就會造成依賴衝突,解決方案如下:
Xml程式碼
將依賴範圍設定成provided,就意味著該依賴對於主原始碼classpath,以及測試classpath可用,但不會被打包。這正是servlet-api所需要的。
這裡歸納一下主要的依賴範圍以及作用:
需要注意的是,當我們沒有宣告依賴範圍的時候,其預設的依賴範圍是compile。
分類器(classifer)
GAV是Maven座標最基本最重要的組成部分,但GAV不是全部。還有一個元素叫做分類器(classifier),90%的情況你不會用到它,但有些時候,分類器非常不可或缺。
舉個簡單的例子,當我們需要依賴TestNG的時候,簡單的宣告GAV會出錯,因為TestNG強制需要你提供分類器,以區別jdk14和jdk15,我們需要這樣宣告對TestNG的依賴:
Xml程式碼
你會注意到maven下載了一個名為testng-5.7-jdk15.jar的檔案。其命名模式實際上是--.。理解了這個模式以後,你就會發現很多檔案其實都是預設構件的分類器擴充套件,如 myapp-1.0-test.jar, myapp-1.0-sources.jar。
分類器還有一個非常有用的用途是:我們可以用它來宣告對test構件的依賴,比如,我們在一個核心模組的src/test/java中宣告瞭一些基礎類,然後我們發現這些測試基礎類對於很多其它模組的測試類都有用。沒有分類器,我們是沒有辦法去依賴src/test/java中的內容的,因為這些內容不會被打包到主構件中,它們單獨的被打包成一個模式為--test.jar的檔案。
我們可以使用分類器來依賴這樣的test構件:
Xml程式碼
理解了分類器,那麼可供依賴的資源就變得更加豐富。
依賴管理(dependencyManagement)
當你只有一個Maven模組的時候,你完全不需要看這個部分。但你心裡應該清楚,只有一個Maven模組的專案基本上只是個玩具。
實際的專案中,你會有一大把的Maven模組,而且你往往發現這些模組有很多依賴是完全專案的,A模組有個對spring的依賴,B模組也有,它們的依賴配置一模一樣,同樣的groupId, artifactId, version,或者還有exclusions, classifer。細心的分會發現這是一種重複,重複就意味著潛在的問題,Maven提供的dependencyManagement就是用來消除這種重複的。
正確的做法是:
1. 在父模組中使用dependencyManagement配置依賴
2. 在子模組中使用dependencies新增依賴
dependencyManagement實際上不會真正引入任何依賴,dependencies才會。但是,當父模組中配置了某個依賴之後,子模組只需使用簡單groupId和artifactId就能自動繼承相應的父模組依賴配置。
這裡是一個來自於《Maven權威指南》的例子:
父模組中如此宣告:
Xml程式碼
...
...
子模組中如此宣告:
...
你依賴配置越複雜,依賴管理所起到的作用就越大,它不僅能夠幫助你簡化配置,它還能夠幫你鞏固依賴配置,也就是說,在整個專案中,對於某個構件(如mysql)的依賴配置只有一種,這樣就能避免引入不同版本的依賴,避免依賴衝突。
小結
本文講述了一些Maven依賴中重要的概念,並透過樣例提供了一些最佳實踐,如依賴歸類,依賴範圍,分類器,以及依賴管理。我的目的是透過淺顯的例子講述那些你實際工作中會需要了解的80%的內容,如果你需要更深入的瞭解,請參考《Maven權威指南》 。[@more@]http://tech.it168.com/a2009/0224/266/000000266570.shtml
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/93029/viewspace-1017809/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Maven依賴管理:控制依賴的傳遞Maven
- Maven依賴管理系統Maven
- Maven快速入門(五)Maven的依賴管理Maven
- Maven的頂級功能——依賴管理Maven
- Maven-Maven統一管理依賴的版本Maven
- Maven依賴範圍及依賴傳遞Maven
- Maven依賴機制Maven
- Maven 依賴關係Maven
- Maven工程依賴配置Maven
- Maven最佳實踐薦Maven
- .Net核心依賴項注入:生命週期和最佳實踐
- 依賴管理和依賴範圍
- Go 專案依賴注入wire工具最佳實踐介紹與使用Go依賴注入
- maven基礎:依賴範圍Maven
- Maven依賴衝突處理Maven
- maven2+依賴傳遞Maven
- Maven依賴版本更新踩坑Maven
- maven最佳實踐:劃分模組Maven
- Maven中如何管理多模組專案的依賴關係Maven
- 微服務下 Spring Boot Maven 工程依賴關係管理微服務Spring BootMaven
- golang 依賴管理Golang
- Maven依賴scope範圍詳解Maven
- maven 將依賴包打入jar中MavenJAR
- Maven依賴中的scope詳解Maven
- maven依賴jar包更新,業務jar需同步更新(業務jar依賴API)MavenJARAPI
- govendor依賴包管理Go
- Maven 原始碼解析:依賴調解是如何實現的?Maven原始碼
- maven依賴衝突以及解決方法Maven
- Maven依賴版本號引發的血案Maven
- maven中新增Servlet和jsp依賴MavenServletJS
- idea Maven新增依賴沒有提示IdeaMaven
- Maven依賴衝突解決總結Maven
- maven解決jar包依賴衝突MavenJAR
- 探索 JavaScript 中的依賴管理及迴圈依賴JavaScript
- eclipse中maven專案不顯示Maven Dependencies依賴EclipseMaven
- maven中的傳遞依賴和傳遞依賴的解除Maven
- PHP依賴管理ComposerPHP
- Flutter 中的依賴管理Flutter