早起版本jersey可能存在的問題

項目中沒用spring 的restTemplate 而是採用 jersey來做rest 的實現,一直用着,也沒發現有什麼不對,後來加入了,以quartz用硬編碼方式實現,結果啓動項目的時候報錯 ,具體信息爲job id重複。後來經排查是因爲:jersey依賴於org.springframework.web.context.ContextLoaderListener初始化 的ApplicationContext,而spring mvc 依賴於org.springframework.web.servlet.DispatcherServlet初始化的ApplicationContext,也就是說jersey和spring mvc 雖然是共用一個ApplicationContext但是ApplicationContext被初始化了兩次,每次都會調用 beanFactory.preInstantiateSingletons()方法,導致了單例的類被初始化兩次,平常使用是沒問題的,只是每個單例類都我實例化了一個對像,恰巧我們的項目中,SchedulJobManager實例化後我們要設置一些JOB ,且這個JOB的ID是不能重複的,就觸了了這個BUG。jersey版本比較老1.4.1,不知新版本的 jersey會不會不存在這問題,且最後我通過修改spring AbstractApplicationContext源碼 解決了這問題,具體排查解決過程如下如下圖

很是奇怪,然後在構造函數中加了一個日誌輸出,下如圖所示,結果發現 Schedul Initializing 這行條了兩次

 

接下來,檢查web.xml 的配置 如下圖所示

後來還懷疑過是不是 jersey這個springServlet搞的鬼,去掉他,還是有同樣的錯 ,當時對這事,有個臨時的解決辦法,加一個全局靜態變量 haveInit,在構造函中設置它爲true PostConstruct標籤的方法run方法中,如haveInit爲true 就什麼也不錯返回。問題是解決了,但不是從根本上解決,於是我在代碼中加了調用棧的打印。如圖所示

打印出來的結果是  ,org.springframework.web.context.ContextLoaderListener和org.springframework.web.servlet.DispatcherServlet分別都初始化了一次 appcationContext導致的,請看下圖

 

解決辦法是修改 spring AbstractApplicationContext類,做這樣的修改:加一個全局靜態變量 haveInitFlg缺省值爲0 ,在finishBeanFactoryInitialization方法中

最後一行代碼beanFactory.preInstantiateSingletons();  修改爲

        if(haveInitFlg==0){
            beanFactory.preInstantiateSingletons();
            haveInitFlg = 1;
        }

即可

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