<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          告別 Maven,趕快使用他!

          共 5250字,需瀏覽 11分鐘

           ·

          2021-12-17 18:31

          Java世界中主要有三大構(gòu)建工具:Ant、MavenGradle。經(jīng)過幾年的發(fā)展,Ant幾乎銷聲匿跡、Maven也日薄西山,而Gradle的發(fā)展則如日中天。筆者有幸見證了Maven的沒落和Gradle的興起。Maven的主要功能主要分為5點,分別是依賴管理系統(tǒng)、多模塊構(gòu)建、一致的項目結(jié)構(gòu)、一致的構(gòu)建模型和插件機制。本文我們主要從這五個方面來分析一下Gradle比起Maven的先進之處。



          1

          依賴管理系統(tǒng)


          Maven為Java世界引入了一個新的依賴管理系統(tǒng)。在Java世界中,可以用groupId、artifactId、version組成的Coordination(坐標(biāo))唯一標(biāo)識一個依賴。任何基于Maven構(gòu)建的項目自身也必須定義這三項屬性,生成的包可以是Jar包,也可以是war包或者ear包。一個典型的依賴引用如下所示:


          <dependency>
          ????<groupId>junitgroupId>

          ????<artifactId>junitartifactId>
          ????<version>4.12version>
          ????<scope>testscope>
          dependency>

          <dependency>
          ????<groupId>org.springframeworkgroupId>
          ????<artifactId>spring-testartifactId>
          dependency>


          從上面可以看出當(dāng)引用一個依賴時,version可以省略掉,這樣在獲取依賴時會選擇最新的版本。而存儲這些組件的倉庫有遠程倉庫和本地倉庫之分。遠程倉庫可以使用世界公用的central倉庫,也可以使用Apache Nexus自建私有倉庫;本地倉庫則在本地計算機上。通過Maven安裝目錄下的settings.xml文件可以配置本地倉庫的路徑,以及采用的遠程倉庫的地址。


          Gradle在設(shè)計的時候基本沿用了Maven的這套依賴管理體系。不過它在引用依賴時還是進行了一些改進。


          首先引用依賴方面變得非常簡潔。


          dependencies?{
          ????compile?'org.hibernate:hibernate-core:3.6.7.Final'
          ????testCompile ‘junit:junit:4.+'
          }


          第二,Maven和Gradle對依賴項的scope有所不同。在Maven世界中,一個依賴項有6種scope,分別是complie(默認(rèn))、provided、runtime、test、system、import。而grade將其簡化為了4種,compile、runtime、testCompile、testRuntime。那么如果想在gradle使用類似于provided的scope怎么辦?別著急,由于gradle語言的強大表現(xiàn)力,我們可以輕松編寫代碼來實現(xiàn)類似于provided scope的概念(例如How to use provided scope for jar file in Gradle build?)。


          https://stackoverflow.com/questions/18738888/how-to-use-provided-scope-for-jar-file-in-gradle-build


          第三點是Gradle支持動態(tài)的版本依賴。在版本號后面使用+號的方式可以實現(xiàn)動態(tài)的版本管理。


          第四點是在解決依賴沖突方面Gradle的實現(xiàn)機制更加明確。使用Maven和Gradle進行依賴管理時都采用的是傳遞性依賴;而如果多個依賴項指向同一個依賴項的不同版本時就會引起依賴沖突。而Maven處理這種依賴關(guān)系往往是噩夢一般的存在。而Gradle在解決依賴沖突方面相對來說比較明確。在Chapter 23. Dependency Management 中的23.2.3章節(jié)詳細解讀了gradle是如何處理版本沖突的。


          https://docs.gradle.org/current/userguide/dependency_management.html



          2

          多模塊構(gòu)建

          ?

          在SOA和微服務(wù)的浪潮下,將一個項目分解為多個模塊已經(jīng)是很通用的一種方式。在Maven中需要定義個parent POM作為一組module的聚合POM。在該POM中可以使用標(biāo)簽來定義一組子模塊。parent POM不會有什么實際構(gòu)建產(chǎn)出。而parent POM中的build配置以及依賴配置都會自動繼承給子module。


          而Gradle也支持多模塊構(gòu)建。而在parent的build.gradle中可以使用allprojects和subprojects代碼塊來分別定義里面的配置是應(yīng)用于所有項目還是子項目。對于子模塊的定義是放置在setttings.gradle文件中的。在gradle的設(shè)計當(dāng)中,每個模塊都是Project的對象實例。而在parent build.gradle中通過allprojects或subprojects可以對這些對象進行各種操作。這無疑比Maven要靈活的多。


          比如在parent的build.gradle中有以下代碼:


          allprojects?{
          ????task?hello << {?task?-> println?"I'm?$task.project.name"?}
          }


          執(zhí)行命令gradle -q hello會依次打印出父module以及各個submodule的項目名稱。這種強大的能力能讓gradle對各個模塊具有更強的定制化。



          3

          一致的項目結(jié)構(gòu)


          在Ant時代大家創(chuàng)建Java項目目錄時比較隨意,然后通過Ant配置指定哪些屬于source,那些屬于testSource等。而Maven在設(shè)計之初的理念就是Conversion over configuration(約定大于配置)。其制定了一套項目目錄結(jié)構(gòu)作為標(biāo)準(zhǔn)的Java項目結(jié)構(gòu)。



          Gradle也沿用了這一標(biāo)準(zhǔn)的目錄結(jié)構(gòu)。如果你在Gradle項目中使用了標(biāo)準(zhǔn)的Maven項目結(jié)構(gòu)的話,那么在Gradle中也無需進行多余的配置,只需在文件中包含apply plugin:'java',系統(tǒng)會自動識別source、resource、test srouce、 test resource等相應(yīng)資源。不過Gradle作為JVM上的構(gòu)建工具,也同時支持groovy、scala等源代碼的構(gòu)建,甚至支持Java、groovy、scala語言的混合構(gòu)建。雖然Maven通過一些插件(比如maven-scala-plugin)也能達到相同目的,但配置方面顯然Gradle要更優(yōu)雅一些。



          4

          一致的構(gòu)建模型


          為了解決Ant中對項目構(gòu)建活動缺乏標(biāo)準(zhǔn)化的問題,Maven特意設(shè)置了標(biāo)準(zhǔn)的項目構(gòu)建周期,其默認(rèn)的構(gòu)建周期如下所示:


          <phases>
          ??<phase>validatephase>

          ??<phase>initializephase>
          ??<phase>generate-sourcesphase>
          ??<phase>process-sourcesphase>
          ??<phase>generate-resourcesphase>
          ??<phase>process-resourcesphase>
          ??<phase>compilephase>
          ??<phase>process-classesphase>
          ??<phase>generate-test-sourcesphase>
          ??<phase>process-test-sourcesphase>
          ??<phase>generate-test-resourcesphase>
          ??<phase>process-test-resourcesphase>
          ??<phase>test-compilephase>
          ??<phase>process-test-classesphase>
          ??<phase>testphase>
          ??<phase>prepare-packagephase>
          ??<phase>packagephase>
          ??<phase>pre-integration-testphase>
          ??<phase>integration-testphase>
          ??<phase>post-integration-testphase>
          ??<phase>verifyphase>
          ??<phase>installphase>
          ??<phase>deployphase>
          phases>


          而這種構(gòu)建周期也是Maven最為人詬病的地方。因為Maven將項目的構(gòu)建周期限制的太死,你無法在構(gòu)建周期中添加新的phase,只能將插件綁定到已有的phase上。而現(xiàn)在項目的構(gòu)建過程變得越來越復(fù)雜,而且多樣化,顯然Maven對這種復(fù)雜度缺少足夠的應(yīng)變能力。比如你想在項目構(gòu)建過程中進行一項壓縮所有javascript的任務(wù),那么就要綁定到Maven的現(xiàn)有的某個phase上,而顯然貌似放在哪個phase都不太合適。而且這些phase都是串行的,整個執(zhí)行下來是一條線,這也限制了Maven的構(gòu)建效率。而Gradle在構(gòu)建模型上則非常靈活。在Gradle世界里可以輕松創(chuàng)建一個task,并隨時通過depends語法建立與已有task的依賴關(guān)系。甚至對于Java項目的構(gòu)建來說,Gradle是通過名為java的插件來包含了一個對Java項目的構(gòu)建周期,這等于Gradle本身直接與項目構(gòu)建周期是解耦的。



          5

          插件機制


          Maven和Gradle設(shè)計時都采用了插件機制。但顯然Gradle更勝一籌。主要原因在于Maven是基于XML進行配置。所以其配置語法太受限于XML。即使實現(xiàn)很小的功能都需要設(shè)計一個插件,建立其與XML配置的關(guān)聯(lián)。比如想在Maven中執(zhí)行一條shell命令,其配置如下:


          <plugin>
          ??<groupId>org.codehaus.mojogroupId>

          ??<artifactId>exec-maven-pluginartifactId>
          ??<version>1.2version>
          ??<executions>
          ????<execution>
          ??????<id>drop DB => db_nameid>
          ??????<phase>pre-integration-testphase>
          ??????<goals>
          ????????<goal>execgoal>
          ??????goals>
          ??????<configuration>
          ????????<executable>curlexecutable>
          ????????<arguments>
          ??????????<argument>-sargument>
          ??????????<argument>-Sargument>
          ??????????<argument>-Xargument>
          ??????????<argument>DELETEargument>
          ??????????<argument>http://${db.server}:${db.port}/db_nameargument>
          ????????arguments>
          ??????configuration>
          ????execution>
          ??executions>
          plugin>


          而在Gradle中則一切變得非常簡單。


          task?dropDB(type: Exec) {
          ?commandLine?‘curl’,’-s’,’s’,’-x’,’DELETE’,"http://${db.server}:{db.port}/db_name"
          }


          在創(chuàng)建自定義插件方面,Maven和Gradle的機制都差不多,都是繼承自插件基類,然后實現(xiàn)要求的方法。這里就不展開說明。


          從以上五個方面可以看出Maven和Gradle的主要差異。Maven的設(shè)計核心Convention Over Configuration被Gradle更加發(fā)揚光大,而Gradle的配置即代碼又超越了Maven。在Gradle中任何配置都可以作為代碼被執(zhí)行的,我們也可以隨時使用已有的Ant腳本(Ant task是Gradle中的一等公民)、Java類庫、Groovy類庫來輔助完成構(gòu)建任務(wù)的編寫。


          這種采用本身語言實現(xiàn)的DSL對本身語言項目進行構(gòu)建管理的例子比比皆是。比如Rake和Ruby、Grunt和JavaScript、Sbt和Ruby…..而Gradle之所以使用Groovy語言實現(xiàn),是因為Groovy比Java語言更具表現(xiàn)力,其語法特性更豐富,又兼具函數(shù)式的特點。這幾年興起的語言(比如Scala、Go、Swift)都屬于強類型的語言,兼具面向?qū)ο蠛秃瘮?shù)式的特點。


          最后想說的Gradle的命令行比Maven的要強大的多。以前寫過一篇文章專門講述了Gradle的命令行操作,詳情請見Gradle命令行黑魔法。


          命令行黑魔法:http://www.huangbowen.net/blog/2013/09/01/command-line-of-gradle/


          來源:cnblogs.com/huang0925/p/5209563.html



          往期推薦



          SpringBoot實現(xiàn)過濾器、攔截器與切片

          大廠一面:說說本機號碼一鍵登錄如何實現(xiàn)?

          從 JDK 8 到 JDK 17,GC 性能大幅提升??!

          Windows 性能超越 Linux?

          你知道強大的Java 8 的Stream流原理嗎?

          JetBrains打造的開發(fā)神器,一套代碼適應(yīng)多端!



          瀏覽 32
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼的 | 黄色毛片儿 | 四虎5151精品成人无码 | 人妻AV在线 | 大鸡巴操小骚逼 |