2 回答

TA貢獻1815條經(jīng)驗 獲得超6個贊
maven傳遞依賴的版本確定規(guī)則,也就是對重復的間接依賴的包的選擇規(guī)則:
1. 在工程的依賴樹上,深度越淺,越被優(yōu)先選擇。如本例中的spring-jms. 由于pom中直接聲明了3.0.2版本的spring-jms,所以3.0.2版本的spring-jms在工程的依賴樹上處在第一層,而activemq-optional所間接依賴的3.0.3版本的spring-jms則是處在工程依賴樹的第二層,則maven會以深度淺者優(yōu)先,所以最后解析的結(jié)果是選擇了3.0.2版本的spring-jms。
2. 若兩個依賴包處于依賴樹上的同一層,則誰在前,選擇誰。如本例中的spring-core.一個是activemq-optional的間接依賴,一個是spring-context的間接依賴,兩個依賴都是處在第二層上,但由于是activemq-optional聲明在前,所以maven優(yōu)先選擇了activemq-optional所依賴的3.0.3的版本!
3. 避免傳遞依賴引起版本問題的最佳實踐?,F(xiàn)在很多的開源框架和工具都開始分模塊打包發(fā)布,比如spring,hibernate都是如此,而這些模塊之間又有可能存在相關的依賴關系,為了避免出現(xiàn)版本不一致問題,比如上例中出現(xiàn)的spring-jms使用的是3.0.2,而spring-core卻使用了3.0.3這種情況,需要我們對一個工程直接依賴的某一框架的多個模塊都要做出聲明,而不要依賴其內(nèi)部的依賴關系來間接引入??偨Y(jié)起來就昌:一般來說,如果工程直接依賴到某一框架的多個模塊,最好全部聲明這些依賴。
Part two:
compile (編譯范圍)
compile是默認的范圍;如果沒有提供一個范圍,那該依賴的范圍就是編譯范圍(包括編譯,測試,運行,打包都能用)。編譯范圍依賴在所有的classpath 中可用,同時它們也會被打包。
provided (已提供范圍)
provided 依賴只有在當JDK 或者一個容器已提供該依賴之后才使用(編譯,測試可用)。例如,如果你開發(fā)了一個web 應用,你可能在編譯 classpath 中需要可用的Servlet API 來編譯一個servlet,但是你不會想要在打包好的WAR 中包含這個Servlet API;這個Servlet API JAR 由你的應用服務器或者servlet 容器提供。已提供范圍的依賴在編譯classpath (不是運行時)可用。它們不是傳遞性的,也不會被打包。
runtime (運行時范圍)
runtime 依賴在運行和測試系統(tǒng)的時候需要(運行時才可用),但在編譯的時候不需要。比如,你可能在編譯的時候只需要JDBC API JAR,而只有在運行的時候才需要JDBC
驅(qū)動實現(xiàn)。
test (測試范圍)
test范圍依賴在一般的編譯和運行時都不需要,它們只有在測試編譯和測試運行階段可用。
system (系統(tǒng)范圍)
system范圍依賴與provided 類似,但是你必須顯式的提供一個對于本地系統(tǒng)中JAR 文件的路徑。這么做是為了允許基于本地對象編譯,而這些對象是系統(tǒng)類庫的一部分。這樣的構件應該是一直可用的,Maven 也不會在倉庫中去尋找它。如果你將一個依賴范圍設置成系統(tǒng)范圍,你必須同時提供一個systemPath 元素。注意該范圍是不推薦使用的(你應該一直盡量去從公共或定制的 Maven 倉庫中引用依賴)。
添加回答
舉報