爲什麼面試要求看過源碼——案例:由於spring聲明週期導致的錯誤

有人總覺得面試造航母,工作擰螺絲釘,java初級面試中經常會問到,spring的生命週期是什麼,啓動之後做了哪些事情,但工作中又沒關係,用不到,沒有任何意義,真的是這樣嗎?

這裏記一次只有瞭解spring的初始順序才能解決的一個小問題。

問題描述

舊版本獲取某數據xxx是依賴數據庫的一張表tb_xxx,新版本要求獲取這些數據將通過調用service_B服務的接口來獲取。按理說,只是將BService的實現類中改爲走接口形式即可,但改完後,發現應用無法啓動!報錯:Dh握手失敗!我沒有修改其他邏輯卻無法啓動,而且我調的這個接口不需要任何加密驗證。作爲一個入職不足兩個月的本科應屆畢業生遇到這種情況我是如何解決的呢?

背景介紹

應用簡介
我們的java web應用service_A是動態的,頁面是動態的,實體類有哪些字段也是動態的,某個實體類有哪些功能要接入哪些服務也是動態的,需要啓動時讀取xml配置文件決定本應用這次是什麼樣子,有什麼能力,技術棧爲SSM,爲了方便自然將加載xml放在 @PostCut 中,即bean創建後來加載這些xml配置文件。

需求和變動
新版本技術棧上我們要切換至Spring Boot,同時有一些功能的變動。解析這些模型配置文件其實還依賴數據庫的一張表tb_xxx,新版本要求獲取這些數據將通過調用service_B服務的接口來獲取。

服務調用簡介
在遠程調用其他服務前,需要先調用尋址服務service_X進行尋址,獲得目標服務的協議、ip、端口、網域信息,然後拿到與自己服務所在網域相同的地址,然後根據指定的負載均衡的算法來獲得目標服務一個可調用的實例,進行調用,敏感接口需要dh握手,數據加解密。


問題定位

我只是將一個走數據庫的service方法改爲了走接口,報錯爲Dh握手失敗,沒有任何改動,說明一定是這個接口調用出了問題,debug排查發現,這個DH錯誤是發生在服務尋址時報錯的,也就是還沒進入我寫的代碼就出錯了,而服務尋址的代碼是內部框架提供的,框架其他人也都在用,爲什麼其他人沒反應?

在IDEA反編譯的框架代碼的尋址部分中打個斷點,一步步調試發現在調用尋址服務service_X時找不到目標主機的ip端口,而框架代碼中這裏直接從緩存中拿的,若果沒有就會拋出NPE,並被上層封裝爲dh錯誤拋出。按理說緩存中應該有尋址服務的ip端口信息。debug查看發現,這個緩存爲空,size=0,說明沒有放入,ctrl alt f7 查找一波,看看哪裏會將祕鑰對放入緩存,發現框架注入了一個Bean: ServiceInfoListener,而這個bean是在監聽到ApplicationContextInitializedEvent之後執行的。

到了這裏,看過spring源碼或者瞭解spring啓動時做了什麼的同學瞬間就知道哪裏的問題了,因爲xml解析太早了,而依賴的服務尋址這時還未初始化,因此無法調用。


解決

臨時方案:
將xml的解析延後至框架的監聽器執行完畢後進行。

後序方案:
與框架組討論,框架將依賴尋址服務service_X 的祕鑰對配置時機提前,提前至 InitializingBean 的afterPropertiesSet時刻,即允許使用框架開發的應用在啓動時進行遠程遠程調用。

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