1. 程式人生 > >Spring Developer Tools 原始碼分析:三、重啟自動配置'

Spring Developer Tools 原始碼分析:三、重啟自動配置'

接上文 Spring Developer Tools 原始碼分析:二、類路徑監控,接下來看看前面提到的這些類是如何配置,如何啟動的。

spring-boot-devtools 使用了 Spring Boot 的自動配置方式,我們先關注本地開發環境中自動重啟的部分。

在 LocalDevToolsAutoConfiguration 主要包含了 LiveReload 和重啟的配置,LiveReload 後續看情況再介紹,這裡先看重啟的配置。

3.1 LocalDevToolsAutoConfiguration 本地配置

在這個類上 @ConditionalOnInitializedRestarter
是一個該配置生效的條件,具體實現中會判斷 Restarter 是否已經例項化,並且是否存在可被監控的類目錄(除 jar 檔案外的目錄),如果已經例項化,並且有需要監控的目錄才會啟動。

通過 java -jar 方式啟動的時候,由於不存在需要監控的目錄,devtools 不會觸發後續的配置,因此雖然啟動了 Restarter,但是並不會監控目錄,也不會自動重啟。

當通過 IDE 啟動專案時,預設情況下會滿足這裡的條件,LocalDevToolsAutoConfiguration 中的其他配置可以生效。

3.2 RestartConfiguration 重啟配置

在 RestartConfiguration 上也有限制條件,只有當設定下面的引數時才不會生效


不設定或者設定為任何不是 false (忽略大小寫)的值時,都會生效。

除了這個引數能控制外,還有一個可以直接控制 Restarter 是否生效的引數,後續會介紹。

下面逐個看 RestartConfiguration 中的各個配置。

3.2.1 FileSystemWatcherFactory 檔案監控

配置程式碼如下:


FileSystemWatcherFactory 是一個函式式介面,這裡直接返回了一個方法引用。將來呼叫該介面的方法時,就會執行下面的 newFileSystemWatcher 方法。

每次呼叫 fileSystemWatcherFactory() 方法時,返回的都是同一個 FileSystemWatcherFactory,但是呼叫工廠的 getFileSystemWatcher() 方法時返回都是新的 FileSystemWatcher。

通過這個方法可以看到建立 FileSystemWatcher 時,這裡會判斷是否配置了觸發檔案(只有修改指定檔案才會重啟),是否配置額外需要監控變化的位置。Java架構交流學習圈:874811168 面向1-3年經驗 Java開發人員 幫助突破瓶頸 提升思維能力

3.2.2 ClassPathRestartStrategy 重啟策略

程式碼如下:


該方法返回了 PatternClassPathRestartStrategy 實現類,判斷是否重啟時,忽略所有傳入的位置,預設忽略的位置如下:


額外的排除項可以通過下面的引數設定:


3.2.3 ClassPathFileSystemWatcher 類路徑監控

程式碼如下:


這裡建立時,從 Restarter 獲取了需要監控的類路徑(後續會詳細介紹),然後建立了一個 watcher,使用了前面建立的兩個 bean。setStopWatcherOnRestart 的意思是當類路徑發生變化並且需要重啟時,是否停止類監控,這裡設定了 true,也就是重啟前會停止監控。

如果重啟前會停止監控,我們可能需要擔心如果配置改錯了導致 Spring 無法啟動該怎麼辦,devtools 也提供了相應的策略來解決這個問題,下一小節就會看到。

3.2.3 監聽 ClassPathChangedEvent

程式碼如下:


當一個方法新增 @EventListener 時,Spring 會把該方法新增到事件監聽中,當觸發該事件時,這個方法就會被呼叫。在上一篇介紹了 ClassPathChangedEvent,其中包含了 restartRequired,這裡會判斷是否需要重啟,當需要重啟時,就會呼叫 Restarter 的例項進行重啟。

在重啟方法中還傳入了 FileWatchingFailureHandler 並且使用了 fileSystemWatcherFactory。

FileWatchingFailureHandler 實現了 FailureHandler 介面,該介面用於在重啟的啟動過程中,如果出錯了,要採取什麼策略去進行下去,該介面方法返回的結果只有兩種,Outcome.ABORT 中止或 Outcome.RETRY 重試。

FileWatchingFailureHandler 中會通過 fileSystemWatcherFactory 建立一個新的檔案監控,當類路徑的內容發生變化時(不需要考慮是否需要重啟,因為已經停止,並且沒啟動成功)就嘗試重新啟動。這種策略可以解決當配置或者程式碼出錯無法啟動時,可以修改BUG解決錯誤,然後 devtools 自動嘗試啟動。

FileWatchingFailureHandler 中的 FileSystemWatcher 和 3.2.3 中的不是同一個,並且在重啟前另一個已經關閉,關閉的目的不是為了防止和這裡存在兩個監控出現衝突,而是為了防止第一次修改後,還沒有重啟時又發生了變化,由於重啟需要時間,這就會導致重啟還沒完成就又重啟了,這種情況下除了會產生錯誤外,還會因為短時間內頻繁重啟導致重啟時間過長。Java架構交流學習圈:874811168 面向1-3年經驗 Java開發人員 幫助突破瓶頸 提升思維能力

在重啟時,會先關閉所有的 Spring Context,此時也會觸發 ClassPathFileSystemWatcher 中的 destroy 方法:


在 destroy 中也會關閉檔案監控,所以無論如何都不會和這裡的 FileSystemWatcher 產生衝突。

3.3 重啟後會重新初始化 Spring

關閉再啟動時,devtools 通過反射執行的我們自己的 XXApplication 類的 main 方法,因此 LocalDevToolsAutoConfiguration 也會重新初始化,類路徑監控也會重新建立。我們現在只是瞭解了從檔案監控、類路徑監控以及監控配置啟動和觸發重啟的過程。有很多關鍵的處理過程和 RestartClassLoader 以及 Restarter 有關,為了防止過長篇幅使得關注點太過分散,後續會分別介紹這兩部分內容。