Lombok 執行路徑
Javac:以註解處理器啟動
使用 javac
(以及 netbeans、maven、gradle 和大多數其他建構系統),lombok 以註解處理器的方式執行。
Lombok 位於類別路徑中,而 javac
將會載入在類別路徑上找到的每個 META-INF/services/javax.annotation.processing.Processor
檔案,讀取每一行並載入該類別,然後以註解處理器的方式執行它。lombok.jar
包含此檔案,其中列出 lombok.launch.AnnotationProcessorHider$AnnotationProcessor
作為條目。
這個類別實際上是不可見的(它是 public 的,但其外部類別 (AnnotationProcessorHider
) 是 package private 的,使其對於 java 語言來說是不可見的),然而,為了 java 虛擬機的目的,它被認為是可見的,因此它將會執行。這個複雜的技巧用於確保任何在類別路徑上使用 lombok 開發的人,其「命名空間」不會被注入 lombok 的類別或 lombok 的依賴項(例如,如果您將 lombok 新增至您的專案,您的 IDE 將不會開始在自動完成對話框中建議 lombok 類別)。
lombok.launch.AnnotationProcessorHider$AnnotationProcessor
類別由 javac
載入、實例化,並在其上呼叫 init()
。這個類別啟動 lombok 的 ShadowClassLoader
;它找到它所在的 jar 檔案,然後將開始從這個 jar 檔案載入類別。它不像一般的載入器那樣尋找以 .class
結尾的檔案,而是尋找以 .SCL.lombok
結尾的檔案(這也是為了將 lombok 的類別從 IDE 等隱藏起來)。透過這個類別載入器,啟動了真正的註解處理器,即 lombok.core.AnnotationProcessor
類別。
lombok.core.AnnotationProcessor
也是一個委派處理器。它可以根據 lombok 發現自己所處的環境委派給 2 個子處理器之一:如果是 javac,則使用 lombok.javac.apt.LombokProcessor
類別(並且如果使用 plexus 編譯器框架,這在使用 javac 編譯時可能會發生,則會執行一些額外的程式碼以將 lombok 修補到其模組化類別載入架構中)。如果是 ecj(eclipse 的編譯器,這表示我們要么在 eclipse 內部執行,要么被調用為 ecj 的註解處理器,即獨立的 eclipse 編譯器),則會將錯誤/警告注入到編譯過程中,以告知使用者他們應該使用不同的參數來在 eclipse/ecj 中使用 lombok。
lombok.javac.apt.LombokProcessor
是「真正」的註解處理器,負責轉換您的程式碼。
程式碼轉換從根本上來說是一個循環概念:為了產生一些程式碼,您需要了解該程式碼(例如,其中有哪些註解),但是當您產生新的程式碼時,解譯它意味著我們重新開始。這同樣適用於 lombok 本身:lombok 的某些轉換會新增方法,然後這些方法會對其他 lombok 轉換產生影響。因此,lombok 將處理程序劃分為「層級」。執行最高層級的所有處理程序,然後強制進行新的註解回合(這會將產生的內容整合到符號表等中),然後執行下一層級的處理程序。這些層級透過 @HandlerPriority
註解指示。您可以透過產生檔案來強制 javac 執行另一個回合。我們實際上不想產生任何檔案,因此我們產生一個虛擬檔案並修補 javac 的 filer,使其實際上不會將 lombok 產生的虛擬檔案儲存到任何地方。各種 HandleX
類別(應用實際的 lombok 轉換)儲存在 HandlerLibrary
中,後者使用 SPI 來發現處理類別。
Eclipse/ECJ:以代理程式啟動
使用 ecj
和 eclipse
,lombok 以「代理程式」的方式啟動。這有點像偵錯器:它讓 lombok 可以在 JVM 實際載入這些類別之前檢查原始類別位元組碼,並且 lombok 將修改此程式碼,以確保 ecj/eclipse 將 lombok 納入編譯過程中。
類別的修補是由 src/eclipseAgent
原始碼目錄中的程式碼完成的。請注意,修補程式碼必須修補 equinox(eclipse 模組系統),以確保 lombok 和 java 編譯模組(在 eclipse 術語中為「JDT」模組)可以彼此看見。
應用了許多針對問題的臨時修復(例如 eclipse 的 format-my-code 功能需要一些戰術性的位元組碼修補,以確保它不會搞亂格式化來源程式碼),但注入到 ecj/eclipse 中的主要「將 lombok 作為編譯過程的一部分執行」的鉤子指向了 lombok.eclipse.TransformEclipseAST
類別,可以將其視為進入點。除非您想搞亂 lombok 如何載入到 eclipse/ecj 中,否則請從這裡開始。
每個 HandleX
類別都透過 SPI 發現,並且 lombok 將在需要時調用處理類別。處理類別找到 lombok 註解並應用所需的轉換。處理程序位於 src/core
原始碼目錄的 lombok.eclipse.handlers
套件中。
VSCode 和 IntelliJ:以插件啟動
在這兩個 IDE 中對 Lombok 的支援由這些 IDE 的插件負責。