久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

一文搞懂 Maven 原理

 520jefferson 2020-11-08

作者簡介

大數(shù)據(jù)研發(fā)工程師,,主要研究 Hive,Presto,Spark 等計算引擎,。有任何問題,,歡迎大家隨時聯(lián)系:

- 知乎: tkanng

- GitHub: tkanng

- Email: [email protected]

Maven 簡介

Maven 是一種聲明式項目管理工具,,通過在 POM 中配置 'who','what','where'等信息,,即可滿足編譯,、測試、打包,、發(fā)布等項目構(gòu)建需求,。聲明式的好處是,用戶無需關(guān)心構(gòu)建工具的實現(xiàn)細(xì)節(jié),,只需在 pom.xml 中配置好項目名,,依賴等基礎(chǔ)信息即可。壞處是,,實現(xiàn)自定義的構(gòu)建邏輯,,相對復(fù)雜。(Maven 也提供了插件,,如:maven-antrun-plugin,,來運(yùn)行用戶自定義腳本。當(dāng)然,,插件最終 apply 到 Maven 的方式最終仍然是聲明式的,,即需要在 POM 中聲明插件運(yùn)行時機(jī)和插件相關(guān)配置。)

相對應(yīng)地,,Make 和 Ant 等構(gòu)建工具是過程式項目管理工具,,用戶需要編寫構(gòu)建腳本并組織各腳本的依賴關(guān)系,。過程式項目管理工具好處是,,用戶自由度很大;壞處是,,項目管理經(jīng)驗無法復(fù)用,,構(gòu)建腳本編寫較為復(fù)雜。

POM

基本概念

POM 文件是Maven的核心文件,,包含項目構(gòu)建相關(guān)的所有配置信息,,如:項目源代碼目錄,class 文件輸出目錄等,。Maven 執(zhí)行 goal 時,,會首先讀取當(dāng)前目錄的 POM 文件,然后執(zhí)行對應(yīng) goal,。

Super POM

Super POM 是 Maven 的默認(rèn) POM,。除顯式聲明以外,所有的POM都繼承自Super POM. Super POM 中配置了默認(rèn)的倉庫地址,,基本的 Plugin 和源代碼路徑等配置,。Super POM 內(nèi)容如下:

<project> <modelVersion>4.0.0</modelVersion> <!-- NOTE: 依賴 repo 和 插件repo默認(rèn)倉庫地址--> <repositories><!-- ....默認(rèn)repo --> </repositories> <pluginRepositories> <pluginRepository><!-- ....默認(rèn)repo --> </pluginRepository> </pluginRepositories> <!-- NOTE: 項目默認(rèn)配置,如:mian代碼目錄,,--> <build> <directory>${project.basedir}/target</directory> <outputDirectory>${project.build.directory}/classes</outputDirectory> <finalName>${project.artifactId}-${project.version}</finalName> <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory> <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory> <resources> <resource> <directory>${project.basedir}/src/main/resources</directory> </resource> </resources> <testResources> <testResource> <directory>${project.basedir}/src/test/resources</directory> </testResource> </testResources> <pluginManagement> <!-- NOTE: These plugins will be removed from future versions of the super POM --> <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) --> <plugins><!-- ....這里是一系列的默認(rèn)插件 --> </plugins> </pluginManagement> </build></project>

Project Inheritance VS Project Aggregation

  • Project Inheritance: 繼承已有pom.xml,,便于做公共配置管理,。Super POM 是 Project Inheritance 的典型例子。

  • Project Aggregation: 同一項目中存在多個module,。

下圖展示了 Presto 的 POM 結(jié)構(gòu),,Presto 項目中既有項目繼承(繼承自io.airlift:airbase:80)也有項目聚合(多個模塊)。

Lifecycle

Maven的生命周期就是為了對所有的構(gòu)建過程進(jìn)行抽象和統(tǒng)一,。

Maven從大量項目和構(gòu)建工具中學(xué)習(xí)和反思,,然后總結(jié)了一套高度完善的、易擴(kuò)展的生命周期,。

Maven 生命周期包含項目清理,、初始化、編譯,、測試,、打包、集成測試,、驗證,、部署和站點生成等幾乎所有構(gòu)建步驟。也就是說,,幾乎所有項目的構(gòu)建,,都能映射到這樣一個生命周期上。

Lifecycle 是抽象的概念,,生命周期本身不做任何實際工作,。

Maven 設(shè)計中,實際工作都交由插件完成,。

Lifecycles VS Phases

Maven 有三套獨立的 Lifecycle:default,、clean 和 site,每個 Lifecycle 包含多個 Phase,。

下圖詳細(xì)的展示了Lifecycle 和 Phase的關(guān)系,。

Default

default生命周期定義了真正構(gòu)建時所需要執(zhí)行的所有步驟,它是所有生命周期中最核心的部分,,其包含的階段如下:

  • validate:驗證項目是否合法以及項目構(gòu)建信息是否完備,。

  • initialize:初始化。

  • generate-sources: 生成源代碼,,如:ANTLR 插件會根據(jù)語法文件生成對應(yīng)的 Java 源代碼,。

    process-sources: 處理項目主資源文件。一般來說,,是對src/main/resources目錄的內(nèi)容進(jìn)行變量替換等工作后,,復(fù)制到項目輸出的主classpath目錄中。

  • generate-resources:生成資源文件,。

  • process-resources:處理資源文件,。

  • compile:編譯項目的主源碼,。一般來說,是編譯src/main/java目錄下的Java文件至項目輸出的主classpath目錄中,。

  • process-classes:處理class文件,,如:字節(jié)碼增強(qiáng)。

  • generate-test-sources:生成測試源代碼,,如:ANTLR,。

  • process-test-sources:處理項目測試資源文件。一般來說,,是對src/test/resources目錄的內(nèi)容進(jìn)行變量替換等工作后,,復(fù)制到項目輸出的測試classpath目錄中。

  • generate-test-resources:生成測試資源文件,。

  • process-test-resources:拷貝或處理測試資源文件至目標(biāo)測試目錄,。

  • test-compile:編譯項目的測試代碼。一般來說,,是編譯src/test/java目錄下的Java文件至項目輸出的測試classpath目錄中,。

  • process-test-classes:處理 test class文件。

  • test:使用單元測試框架運(yùn)行測試,,測試代碼不會被打包或部署,。

  • prepare-package:打包前置工作。

  • package:接受編譯好的代碼,,打包成可發(fā)布的格式,,如JAR,WAR等,。

  • pre-integration-test:集成測試的前置工作

  • integration-test:集成測試,。

  • post-integration-test :集成測試后,,需要做的一些事情,。

  • verify:檢測所有的集成測試結(jié)果是否符合預(yù)期,保障代碼質(zhì)量,。

  • install:將包安裝到Maven本地倉庫,,供本地其他Maven項目使用。

  • deploy:將最終的包復(fù)制到遠(yuǎn)程倉庫,,供其他開發(fā)人員和Maven項目使用,。

Clean

clean 生命周期的目的主要是清理項目。

  • pre-clean:執(zhí)行一些清理前需要完成的工作,。

  • clean:清理上一次構(gòu)建生成的文件,。

  • post-clean:執(zhí)行一些清理后需要完成的工作。

Site

site 生命周期用于生成代碼站點文檔并發(fā)布至對應(yīng)Web Server,。

  • pre-site:前置工作,。

  • site:生成代碼對應(yīng)的站點文檔,。

  • post-site:site后置工作,deploy 前置工作,。

  • site-deploy:發(fā)布站點文檔至對應(yīng)的Web Server,。

Plugins

一個 Plugin 包含多個goal,來完成項目構(gòu)建的實際工作,,如:Compiler plugin 有兩個goal compile 和 testCompile,,分別用于編譯main代碼與編譯test代碼。下圖是default生命周期的插件內(nèi)置綁定與具體goal的綁定關(guān)系:

常用 Plugin

maven-shade-plugin

maven-shade-plugin 是一個很強(qiáng)大的 Maven 插件,,可以用來relocate 包名,,解決依賴沖突問題;也可以生成一個可執(zhí)行Jar包(又稱 Uber Jar),。下面我們就簡單介紹下這兩個功能使用方法,。

Relocation

我們以shade hive-exec 中的guava包進(jìn)行說明。(hive-exec 會依賴calcite的代碼,,calcite代碼也會依賴guava包),。

shaded-exec pom.xml:

shaded-exec 中 calcite 代碼:

結(jié)論:maven-shade-plugin 會對滿足對應(yīng)pattern的所有class文件進(jìn)行relocate,不會區(qū)分該class文件是否是本項目代碼編譯產(chǎn)生,。

Executable Jar

結(jié)論:默認(rèn)情況下,,maven-shade-plugin 產(chǎn)生的 shaded jar,包含當(dāng)前項目class文件以及compile依賴。這也是為什么有時候可以通過修改依賴的scope,,即可影響JAR內(nèi)容的,。然而,如果項目中僅使用了默認(rèn)的jar plugin,,那么修改依賴scope,,將不會影響輸出的Jar的內(nèi)容了,里面將永遠(yuǎn)只包含本項目的class,。

maven-antrun-plugin

maven-antrun-plugin 使Maven可以運(yùn)行我們自定義的腳本,,靈活控制構(gòu)建過程。

如下所示 pom.xml 就通過 maven-antrun-plugin 在 compile 階段打印出 Maven 的四類class path,,幫助我們定位編譯問題,。

<project>  <build>    <plugins>      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-antrun-plugin</artifactId>        <version>3.0.0</version>        <executions>          <execution>            <id>compile</id>            <phase>compile</phase>            <configuration>              <target>                <property name='compile_classpath' refid='maven.compile.classpath'/>                <property name='runtime_classpath' refid='maven.runtime.classpath'/>                <property name='test_classpath' refid='maven.test.classpath'/>                <property name='plugin_classpath' refid='maven.plugin.classpath'/>
<echo message='compile classpath: ${compile_classpath}'/> <echo message='runtime classpath: ${runtime_classpath}'/> <echo message='test classpath: ${test_classpath}'/> <echo message='plugin classpath: ${plugin_classpath}'/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> </plugins> </build></project>

PS:當(dāng)插件目標(biāo)被綁定到不同的生命周期階段的時候,其執(zhí)行順序會由生命周期階段的先后順序決定,。如果多個目標(biāo)被綁定到同一個階段,,它們的執(zhí)行順序會是怎樣?

答:當(dāng)多個插件目標(biāo)綁定到同一個階段的時候,,這些插件聲明的先后順序決定了目標(biāo)的執(zhí)行順序,。

Dependency Mechanism

Maven 作為一個項目管理工具,依賴管理是必不可少的,。

Maven 依賴坐標(biāo)

Maven 坐標(biāo)為各種構(gòu)件引入了秩序,,任何一個構(gòu)件都必須明確定義自己的坐標(biāo),,而一組Maven坐標(biāo)是通過一些元素定義的,。Maven 坐標(biāo)一般可以認(rèn)為是一個五元組,,即:(groupId,artifactId,,version,,type,classifier),。下面進(jìn)行詳細(xì)說明:

  • groupId:Maven 項目隸屬的實際項目名稱,。

  • artifactId:實際項目中的一個模塊名稱。

  • version:版本,。

  • type:

     –jar: jar包,,包含依賴項目主代碼 class文件。

     –test-jar:jar包,,classifier 為 tests,,包含依賴項目測試代碼 class 文件。用于復(fù)用測試代碼,。

  • classifier: 用于區(qū)分從同一個POM中,,構(gòu)建出的不同 artifacts。比如:同一個項目可能同時提供 jdk11 和 jdk 8 對應(yīng)的依賴,,同一個項目可能同時提供shaded 和 un-shaded 的依賴版本等,。

上述五個元素中,groupId,、artifactId,、version是必須定義的,type是可選的(默認(rèn)為jar),,而classifier是取決于對應(yīng)依賴是否提供。

<project xmlns='http://maven./POM/4.0.0' xmlns:xsi='http://www./2001/XMLSchema-instance' xsi:schemaLocation='http://maven./POM/4.0.0 https://maven./xsd/maven-4.0.0.xsd'> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <type>jar</type> <scope>test</scope> <optional>true</optional> </dependency> <dependency> <groupId>mygroup</groupId> <artifactId>myjar</artifactId> <version>1.0</version> <classifier>jdk11</classifier> </dependency> <dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-common</artifactId> <version>1.0</version> <scope>test</scope> <type>test-jar</type> </dependency> </dependencies></project>

依賴 Scope

依賴Scope作用有兩個:

1. 限制依賴傳遞

2. 控制依賴是否出現(xiàn)在各個classpath中

Maven 中有五種依賴scope,,分別是:compile,provided,runtime,test和system,。

下面是引用自Maven官網(wǎng)的說明:

Maven中大致可以分成四類class path:

  • main 代碼編譯classpath:編譯main代碼的classpath

  • main 代碼運(yùn)行classpath:運(yùn)行main代碼的classpath

  • test 代碼編譯classpath:編譯測試代碼的classpath

  • test 代碼運(yùn)行classpath:運(yùn)行測試代碼的classpath

結(jié)合依賴的scope和四類classpath,總結(jié)出 classpath 與 依賴的關(guān)系,,如下圖:

依賴傳遞

  • A -> B (compile) 第一關(guān)系 : A 依賴 B compile

  • B -> C (compile) 第二關(guān)系 : B 依賴 C compile

當(dāng)在A中配置:  

<dependency>              <groupId>com.B</groupId>              <artifactId>B</artifactId>              <version>1.0</version>  </dependency>

則會自動導(dǎo)入 C 包,, 詳細(xì)的關(guān)系傳遞如下表 :

依賴調(diào)節(jié)

依賴調(diào)解遵循以下兩大原則:路徑最短優(yōu)先,、聲明順序優(yōu)先。

  • 第一原則:路徑最近者優(yōu)先,。把當(dāng)前模塊當(dāng)作頂層模塊,,直接依賴的包則作為次層模塊,間接依賴的包則作為次層模塊的次層模塊,,依次遞推...,,最后構(gòu)成一棵引用依賴樹。假設(shè)當(dāng)前模塊是A,,兩種依賴路徑如下所示:

A --> B --> X(1.1) // dist(A->X) = 2A --> C --> D --> X(1.0) // dist(A->X) = 3

此時,,Maven可以按照第一原則自動調(diào)解依賴,結(jié)果是使用X(1.1)作為依賴,。

  • 第二原則:第一聲明者優(yōu)先,。若沖突依賴的路徑長度相同,那么第一原則就無法起作用了,。假設(shè)當(dāng)前模塊是A,,兩種依賴路徑如下所示:

A --> B --> X(1.1)   // dist(A->X) = 2 A --> C --> X(1.0)   // dist(A->X) = 2

當(dāng)路徑長度相同,則需要根據(jù)A直接依賴包在pom文件中的先后順序來判定使用那條依賴路徑,,如果次級模塊相同則向下級模塊推,,直至可以判斷先后位置為止。

<!-- A pom.xml --><dependencies> ... dependency B ... dependency C</dependencies>

假設(shè)依賴B位置在依賴C之前,,則最終會選擇X(1.1)依賴,。

  • 其它情況:覆蓋策略。若相同類型但版本不同的依賴存在于同一個pom文件,,依賴調(diào)解兩大原則都不起作用,,需要采用覆蓋策略來調(diào)解依賴沖突,最終會引入最后一個聲明的依賴,。

<!-- 該pom文件最終引入commons-cli:commons-cli:1.3.jar依賴包,。 -->
<dependencies> <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.3</version> </dependency></dependencies>

總結(jié)

1.Maven 是一種聲明式的項目管理工具。

2.Maven 有3套獨立的生命周期,,具體的工作交由插件 goal 完成,。

3.修改依賴Scope,并不能控制Jar的內(nèi)容,。

Hey!

我是小蘿卜算子

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多