1. 程式人生 > >記錄一次升級公司框架導致的service注入失敗的問題

記錄一次升級公司框架導致的service注入失敗的問題

背景:公司使用的還是jdk7,早就想升級到jdk8,但是很坑爹的是,公司的框架使用的是Netty3.2.7和spring3.x,不能升級,jdk8必須使用spring4.x才可以,當然,spring4.x可以向下相容jdk7.思考再三,長痛不如短痛,升級Netty3.2.7到Netty4.1.31(Netty最新版本是5.x但是廢棄了,不建議使用),spring3.x升級到spring4.3.20,這樣就可以升級到jdk8了

Netty4.x居然不相容Netty3.x,連包名都換了,升級到4.1.31的過程是痛苦的,程式碼各種紅,各種踩坑,這不是本篇重點,後面寫部落格一遍Netty升級的踩坑記錄

問題:升級以後,Controller注入service失敗,跟蹤發現為null,如下圖:

最初猜測是spring沒有載入到,因此寫了工具類來驗證,如下圖:

可以看到,的確是拿到了注入的service,但是為啥是null呢?

難道拿到的controller和當前controller不是同一個嘛?

居然還真不是同一個,那麼注入失敗,也就找到原因了,下面排查為啥不是同一個controller

跟蹤公司框架原始碼,發現如下程式碼:

用反射獲取的Controller,然後反射呼叫:

那麼問題就在這裡了,最初除錯的this controller是反射獲取的,當然注入失敗,無法呼叫了

嘗試解決:

(1)反射獲取的bean,如何注入spring bean物件呢?

 先獲取spring中的controller,然後,修改呼叫引數,如下所示:

invokeBizMethod(course,messsage);修改為:

invokeBizMethod((BusinessCourse) ApplicationContextHelper.getBean(ClassUtil.getClassLowerName(course.getClass())), message);

除錯發現也不行,因為這個時候Controller不一定被Spring載入到,因為,Spring中載入bean的順序是不定的,當然,如果能控制Controller的載入順序先於反射呼叫的地方,也是可以解決問題的,問題轉化為(2)中的bean載入順序問題。

(2)不用反射拿物件,直接問Spring要

不能框架層反射獲取,那麼就在專案中直接獲取,因為用的是springBoot,沒有配置檔案,因此笨辦法寫一個ControllerCollect的輔助類去獲取,然後賦值

需要賦值的地方如下:

這樣可以解決問題,但是太low了

修改如下:在Controller的基類BaseController中直接獲取

然後賦值語句 更新為  httpBizEntry.setCourses(BaseController.courses);

但是這樣發現賦值為[],也就是沒有賦值成功,分析原因,是spring中bean載入順序問題。因為賦值的地方也是@Bean註解修飾的,

那麼獲取coureses的bean必須先於賦值地方的這個bean載入才可以,這樣需要解決的就是如何控制spring中bean的載入順序問題。

Spring中bean的載入順序,根據需要有明顯的載入依賴關係,首先,可以在程式碼中手動初始化載入,當然這個肯定不會用了,其次考慮用@DependOn註解來控制,但是Controller是多個,只要繼承了BaseController的都是,並且需要指定bean name,分析以後,不符合要求。最後,考慮用@Order註解來控制,修改如下:

問題解決,其實如果使用配置檔案,直接xml裡面配置,就不會出現這個問題,現在雖然解決了問題,但是也需要在程式碼裡面配置,還是不夠友好,後面還是需要考慮如何在框架層處理掉,待完善。