項目中沒用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()方法,致使了單例的類被初始化兩次,日常使用是沒問題的,只是每一個單例類都實例化了兩個對像(bean工廠中,你訪問到的是第二次實例化的),恰巧咱們的項目中,SchedulJobManager實例化後咱們要設置一些JOB ,且這個JOB的ID是不能重複的,就觸發了這個BUG。jersey版本比較老1.4.1,不知新版本的 jersey會不會不存在這問題,且最後我經過修改spring AbstractApplicationContext源碼 解決了這問題,具體排查解決過程以下以下圖web
非常奇怪,而後在構造函數中加了一個日誌輸出,下如圖所示,結果發現 Schedul Initializing 這行條了兩次spring
接下來,檢查web.xml 的配置 以下圖所示mvc
後來還懷疑過是否是 jersey這個springServlet搞的鬼,去掉他,仍是有一樣的錯 ,當時對這事,有個臨時的解決辦法,加一個全局靜態變量 haveInit,在構造函中設置它爲true PostConstruct標籤的方法run方法中,如haveInit爲true 就什麼也不錯返回。問題是解決了,但不是從根本上解決,因而我在代碼中加了調用棧的打印。如圖所示app
打印出來的結果是 ,org.springframework.web.context.ContextLoaderListener和org.springframework.web.servlet.DispatcherServlet分別都初始化了一次 appcationContext致使的,請看下圖函數
解決辦法是修改 spring AbstractApplicationContext類,作這樣的修改:加一個全局靜態變量 haveInitFlg缺省值爲0 ,在finishBeanFactoryInitialization方法中編碼
最後一行代碼beanFactory.preInstantiateSingletons(); 修改成spa
if(haveInitFlg==0){
beanFactory.preInstantiateSingletons();
haveInitFlg = 1;
}rest
便可日誌