Maven和Tomcat能有啥聯絡呢,都穿打補丁的衣服嗎
前奏
我們上篇文章,跟大家說了下,怎麼除錯maven外掛的程式碼,注意,是外掛的程式碼。外掛,是要讓主框架來執行的,主框架是誰呢,就是maven core,可以稱之為maven核心吧。
maven核心,類似於tomcat,而maven外掛就類似於我們部署在tomcat中的webapp應用。估計有人覺得,這個類比有點生硬,不過我也是有我自己的依據的。
下面開始正文。
tomcat的類分散在哪幾處
按照簡單的模型來分,三處:
1、bin下邊的啟動類等
2、lib下的tomcat核心框架類
3、webapp的類
這個就不說了,就是大家的業務類。
maven和tomcat的相似之處
下邊,我們看maven的jar包的分散情況。
1、啟動類
在maven home的boot目錄下
2、maven core
3、外掛程式碼
分佈在本地倉庫中的目錄中。
彙總一下,這兩個框架,執行過程中需要用到的jar包,都分散在了三個地方。按照我們的理解,執行順序是:
從啟動類出發 --》 載入框架核心程式碼 --》 框架去載入外掛/webapp程式碼來執行。
當然了,大家可以想想啊,換成你來寫這個tomcat、maven,你怎麼辦?三種程式碼,三個地方,肯定要三個類載入器吧。第一個類載入器,只能載入到啟動類那幾個包;要去呼叫框架核心,是不是又得新建一個類載入器;框架核心,要去呼叫外掛/webapp程式碼,又要新疆類載入器吧。
中間怎麼銜接啊?
maven clean時,到底發生了什麼(啟動類階段)
如果我們直接在命令列執行mvn clean,實際上是呼叫了 如下命令:
這個命令是啥呢,我之前工作多年的經驗告訴我,這是個二進位制,開啟必須是一串亂碼啊;然後之前對maven也沒好奇心,沒研究過,最近才知道,這他麼是個shell/cmd。
原來是個java命令?? 果然啊,經驗主義還是要不得,大意了大意了。
我這邊是個windows電腦,實在不方便列印出來最終的執行命令,於是採用了一些迂迴方式。
在我的F:\tools\apache-maven-3.8.1-bin\apache-maven-3.8.1\bin
目錄下,開啟git bash,用shell來執行:
大家可以看下,這裡的classpath中的jar,就是我前文提到的,maven home的boot目錄下的 jar,啟動類,就是在這個jar裡面。
這裡,大家可以想想啟動類的目標是啥,是要去載入框架核心。對於啟動類來說,重點在於:框架類的程式碼在哪裡呢?是靠預設約定嗎,還是讀一個什麼配置檔案。
答案就是配置檔案。
可以看看上面的圖裡,有一條:
-Dclassworlds.conf=/f/tools/apache-maven-3.8.1-bin/apache-maven-3.8.1/bin/m2.conf
這個檔案,我們開啟看一下:
main is org.apache.maven.cli.MavenCli from plexus.core
set maven.conf default ${maven.home}/conf
[plexus.core]
load ${maven.conf}/logging
optionally ${maven.home}/lib/ext/*.jar
load ${maven.home}/lib/*.jar
就是個文字檔案啊,裡面好像寫了些似是而非的東西,不能看懂得多了,但是看得懂一點點。
這裡呢,我提煉一下關鍵資訊,其實有三點:
-
接下來要把執行權交給誰?
這個就是從
main is org.apache.maven.cli.MavenCli from plexus.core
這一行,org.apache.maven.cli.MavenCli
就是接下來的框架核心程式碼的啟動人 -
主配置檔案在哪裡
在maven安裝目錄的conf下,這裡面有我們的settings.xml,這個大家都曉得了哈
-
框架核心程式碼在哪裡
這就交給下面幾位來指定了
load ${maven.conf}/logging optionally ${maven.home}/lib/ext/*.jar load ${maven.home}/lib/*.jar
maven clean時,到底發生了什麼(框架核心類階段)
這個階段,內容就太多了,${maven.home}/lib/*.jar
這足足十來個jar包,後面有的是時間說。
我們現在重要的是,把流程先梳理通,框架核心的目標,就是根據引數,找到對應的外掛程式碼,載入進來,然後執行。
我們前面,傳參就是clean,clean其實是代表了clean這個生命週期裡的clean階段,而clean階段,繫結的外掛就是:maven-clean-plugin
。
那這個外掛的程式碼,去哪裡找呢?這次,就是maven 約定優於配置的理念的體現了,沒有采用配置檔案,外掛和我們的業務依賴一樣,都放在本地倉庫,本地倉庫找不到,就去遠端中央倉庫下載。
我們這裡,本地已經有了:
拿到jar後,就是建立一個專供該外掛的類載入器,來載入這個外掛的jar,以及外掛依賴的jar。
外掛依賴的jar,能在哪裡看呢,在這個外掛的描述檔案裡,描述檔案就是下邊這個,它描述了外掛的方方面面,比如有哪些可以執行的goal、goal的引數是啥,當然,也包括了外掛依賴的jar。
外掛依賴如下:
maven clean時,到底發生了什麼(外掛被框架核心執行階段)
框架是被執行的。為什麼叫:被執行。就是,一切的掌控邏輯,都在框架核心中。
外掛呢,是要按照規範來的,誰的規範,框架核心的規範,規範是啥,就是框架核心定的一個介面:
public interface Mojo {
// 外掛邏輯寫在這個裡面
void execute() throws MojoExecutionException, MojoFailureException;
void setLog(Log var1);
Log getLog();
}
clean外掛的實現邏輯:
框架核心做了啥,就是載入org.apache.maven.plugin.clean.CleanMojo
,然後強制向上轉型成Mojo
,然後優雅地用多型來執行execute
方法,呼叫外掛的實際邏輯即可。
maven上述執行過程中的幾個類載入器例項賞析
我在外掛裡,睡了1000秒,然後執行 jmap -dump:live,format=b,file=heap16380.bin 16380
(16380是我maven這個java程式的pid)
把堆dump下來後,還是照例分析一把,看看堆裡有哪些類載入器:
一共18個,還真不少。不過很多都是不用關心的,上圖中,我們只關注三個:
1、啟動時的載入器-AppClassloader
2、框架核心類載入器
如我們所見,確實都是 lib下的jar。
3、外掛類載入器
如我們所見,去本地倉庫載入了外掛的jar。
總結
本來吧,我是想講maven框架核心的除錯環境搭建,結果,就來了個這,畢竟,不把這個說清楚,環境搭建感覺也說不清。。
環境搭建等下篇,see u,以上。