SpringBoot項目啓動過程源碼終於整體捋了一遍(完結)

上篇看到了refreshContext()方法:

refresh()分析完了,接下來看一下這個shutdownHook,擼源碼之前先介紹一下它。

我們做開發的經常需要考慮服務宕機的情況,OOM內存溢出也好,斷電斷網也好,甚至用戶直接點了叉強制退出了。如果服務正在進行很重要的操作處理很重要的數據這個時候進程掛掉了,那之前的活豈不是白乾了,甚至還會導致系統bug。所以這個時候我們希望在服務宕機之前能給我們機會做一些補救措施,比如把處理一半的數據保存下來或者銷燬之類啊,java還真提供了這種機會,就是添加鉤子函數。

代碼核心就一句:Runtime.addShutDownHook(Thread hook),寫了一個例子看一下:

這裏出現異常線程掛掉之前執行了hook thread。如果沒有異常呢:

可以看到沒有異常的話線程執行完退出之前也會執行這個hook thread。看來鉤子裏重寫的run()方法中,我們要自己判斷是否需要執行補救措施,線程正常執行完就不需要什麼補救措施了嘛。Spring添加鉤子函數也很簡單。ApplicationContext.registerShutdownHook();這一行代碼就行了,當然裏面停機前的邏輯也是人家寫好的。

這個shutdownHook用法大致就這介紹完了,繼續擼一下refreshContext()方法的源碼,先是判斷this.registerShutdownHook這個布爾型變量,如果是真的話執行了context.registerShutdownHook();哈好眼熟,這不就是剛說的Spring添加鉤子函數的方法嘛,看來Spring boot添加鉤子函數還有一個方法,就是設置這個this.registerShutdownHook:

而且這個this.registerShutdownHook是默認爲true的,也就是說Spring Boot默認是添加的優雅停機的鉤子函數的,看一下這個registerShutdownHook()方法:

這就和剛剛介紹的鉤子函數的例子對上了,主要看doClose()方法,看看spring在宕機前做了什麼事,方法就不貼了,感興趣的可以去看一下,主要就是bean的destroy和Spring容器的關閉,這樣做到平滑關閉。

到這裏context三連的第二連refreshContext也看完了,再貼一下三連:

 繼續看afterRefresh():

就這?好吧,看來是留給自定義SpringApplication的時候重寫用的。context三連就看完了,回到run()方法中:

 繼續往下看:

這就是個計時的,第六篇提到過(https://blog.csdn.net/weixin_42447959/article/details/105263684),這裏是stop計時停止了,然後把耗時通過啓動日誌打印出來。

繼續往下看:

又開始 發佈事件了,這裏發佈的是ApplicationStartedEvent事件,關於事件發佈機制第六篇(https://blog.csdn.net/weixin_42447959/article/details/105263684)有詳細介紹。

繼續往下看:

看一下這個方法:

 

 先是加載Bean容器中ApplicationRunner和CommanLineRunner的子類,然後遍歷執行重載的callRunner()方法:

本質上就是把Bean容器中ApplicationRunner和CommanLineRunner的子類的run()方法都執行一遍,具體幹了什麼就要去看有哪些子類了,這裏不多介紹。

跳過異常繼續往下看:

 這裏是發佈了ApplicationReadyEvent事件。

我的天!

雖然有點虎頭蛇尾,不過算是終於擼完了,總結一下就是Sping Boot的啓動過程中事件發佈機制真的很重要,發佈了一個事件有好幾個監聽執行了自己的邏輯,如果要把Spring Boot的啓動過程弄得明明白白恐怕要把spring.factories裏面的這些監聽器都看一遍了,包括剛剛說的ApplicationRunner和CommanLineRunner的子類,這些都在Bean容器中。不過有了概念之後問題解決確實快了很多,都說學習是需要反饋的,最近擼這段源碼的時間,自己工作上正好需要把一個Spring MVC+JSP的老項目用Spring Boot重構一下,說實話有些東西清晰好多,這段擼源碼的反饋來的也太快了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章