【曹工雜談】詳解Maven外掛除錯方法

三國夢迴發表於2021-09-06

前言

今年的更新頻率簡直是降至冰點了,一方面平時加班相對多一些了,下班只想玩手機;另一方面,好像進了大廠後,學習動力也很低了,總之就,很懶散,部落格的話,今年都才只更新了不到5篇。

現在慢慢有一點狀態,開始學點技術;今天這篇就是講maven外掛,為啥會折騰這個,公司內有個mybatis generator,針對公司內部做了一些定製開發,具體內容不知道,但是,有個很蛋疼的問題,在根據資料庫表,反向生成po的時候,不能把資料庫表的欄位的註釋,給生成為po的field 註釋。

之前試過自己折騰一下,解決這個問題,但是實在不瞭解maven外掛這塊,因此一直就忍了將就用,大不了就沒有註釋嘛;前幾個月就把maven原始碼下載下來了,但是原始碼裡一堆的單元測試,卻一直不知道怎麼像我們平時使用的方式那樣去debug,最後就三天打魚兩天曬網地瞎看,效果很差,看了多少就忘多少,最近才把debug外掛的方式折騰ok,這裡就分享給大家。

下邊正文。

越是複雜的開源專案,裡面用到的maven外掛就越多,一個pom,大幾百行是常事,經常呢,大家都是隻知道怎麼配置,或者說,不知道怎麼配置,需要改配置的時候,就一頓猛搜,經常網上搜出來的,可能還因為版本不匹配發生“他文章裡可以,我這邊為啥不行”。

反正,總結一句話,maven外掛很多時候,對大家來說,就是一個黑盒。

而我們恰恰不太能忍受黑盒,當然了,像什麼jvm那種c++寫的黑盒就算了,讓人頭禿。

另外,可以再給大家一個看這篇文章的理由,就問你一個問題:spring boot是怎麼打包成fat jar,又是怎麼從一個fat jar啟動的?

是吧,這裡的答案就在spring boot的maven外掛裡了。今天我們肯定不會那麼複雜,搞個clean外掛學習下,就ok了。

怎麼單行除錯一個外掛的原始碼呢

建立演示工程

我們需要一個maven的project,最終弄完,我這邊樣子是這樣的:

下邊是步驟:直接像下面這樣生成一個,然後next結束:

為了方便演示,我們pom.xml裡,刪除了元素裡的內容(主要是被外掛版本的管理,我們為了演示,直接刪了,用預設版本就行),刪除後的pom如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>test-project</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>test-project</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
  </build>
</project>

大家看上面這個pom,很乾淨,會不會以為這樣就沒有配置外掛了呢,不是的,預設的,就會給我們的maven的生命週期繫結一些外掛,比如在clean階段繫結maven-clean-plugin外掛。可以看我下圖,可以看到這裡還是有好幾個外掛的,為了力求簡單好理解,我們關注clean外掛,我這邊是2.5版本,大家對於版本號不用糾結,可能不同的idea版本出來的會有差異。

除錯clean外掛

怎麼除錯呢,首先得觸發maven的clean外掛執行,是吧?怎麼觸發執行呢?

如何觸發執行clean外掛

針對這種命令很簡單的,不需要給外掛傳引數的命令,直接上圖這樣就可以觸發除錯執行。

大家來看看執行效果:

上面這一串,看起來很長,其實很多都是-D指定的SystemProperty和classpath,最終呢,其實就是java -main類 -args的格式。

這裡的引數就是"clean:clean"。

去哪裡打斷點

有人開始問了,你不是說除錯嗎,這都一把跑完了啊,再說了,我想打斷點去哪裡打呢?

ok,要打斷點,我們得知道,mvn clean肯定會執行到的那個方法,然後才能在那裡提前打斷點埋伏,就好像我們總是知道,程式執行,會進入main方法一樣。

而mvn clean,一定會執行到clean外掛中的CleanMojo這個class(這部分知識算是需要提前瞭解的部分):

要除錯這個類,必須得在當前的project(idea裡,一個project包含多個module)裡,能找到這個class。在idea裡,老子上來就是double shift,

看起來,找不到這個類啊,還怎麼玩?最簡單的辦法是,先直接把這個jar包加到project裡面,

新增到libraries裡:

加的時候,會提示你,要不要加入到當前這個project,要選:yes。加了後,就可以看到:

老子抬手又是doubel shift,可以看到,這個cleanMojo已經存在了。

既然存在了,接下來就是打斷點:

繼續觸發執行debug

可以看到,已經成功停在了我們的斷點上,接下來單步除錯就行。但是哈,大家也注意到,我們這邊因為是打在反編譯的class上的,而反編譯的class呢,肯定沒有原始碼那麼舒服的,這個問題呢,也簡單,等我循序漸進來講。

去哪裡打斷點--方式2

我們下邊這個方式,當然是想辦法在原始碼上打斷點,原始碼去哪裡獲取?

https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-clean-plugin/2.5

原始碼下載下來後,我嘗試了下圖這樣的方式(就是在前面方案的基礎上,把原始碼附上了):

這種方式,打個斷點,看看:

這個方式是可以除錯外掛本身那幾個java檔案,但是外掛依賴的那些,就還是有問題,這種方式吧,雞肋。

去哪裡打斷點--最推薦的方式

我們還是不搞那些有的沒的了,來官方的外掛開發地址拉程式碼:

https://maven.apache.org/scm.html

下載後解壓,發現是個maven工程,舒服了。直接匯入idea。匯入後,我們打好了斷點,下邊開始,跑一波debug。

可以看到,這把舒服了,確確實實,除錯的是原始碼了。但是,這裡提醒一下,不要想著去改程式碼,如果直接改,改了肯定就class和java原始碼的行號,對應不上了,至於為什麼,這是一個值得大書特書的故事了,留待後續。

擴充套件

前面我們說的,觸發maven clean執行,是用的這種方式。

實際上,這種只能應付簡單場景,不需要傳參什麼的,複雜場景還是需要像下面這樣:

比如,我們公司的那個mybatis 生成器:

就會指定很多引數,比如對應的配置檔案的位置,對吧。

相關文章