Spring 多線程bean的問題(Spring+Javaweb中任務調度)

在寫一個文件暫存系統的時候,有這樣的一個需求:一個定時任務,每隔t分鐘,做一些掃描操作。

實現思路是繼承ContextLoaderListener,實現自己的Listener,在這個Listener中,開啓定時任務。

一開始直接使用@Componet註解+@Autowired註解,結果導致注入失敗。

由於一開始沒意識到是線程的原因,所以在上網搜的原因及解決方案都是無效的,但也有一些有用的知識:

1.一般@Autowired注入失敗有以下一個原因:

1.包沒掃描到。

2.controller層的@controller或者service層的@Service註解沒寫

3.如果使用@Resource 注入service需要注意對象名字。

2.默認情況下,<context:component-scan>查找使用構造型(stereotype)註解所標註的類,如@Component(組件)@Service(服務),@Controller(控制器),@Repository(數據倉庫)。

3.SpringSpringMVC整合的問題,二者在整合的時候,會產生兩個容器,一個Spring容器,一個SpringMVC容器。Spring容器是父容器,SpringMVC容器是Spring容器的子容器。Spring容器初始化後,SpringMVC再進行初始化,並將Spring容器作爲它的父容器。

子容器能夠訪問父容器的bean,而反之不行。

當父容器的初始化路徑(base-package)等於或者包括了子容器的路徑,那麼可能出現,當SpringMVC子容器初始化時,如果發現有相同的類,會將新初始化的實例覆蓋Spring容器中已經存在的實例,這可能導致注入失敗,空指針的問題。

所以要做到2個容器要掃描的包必須相互區分,互不干擾。Spring容器掃描非Controller的實例,而SpringMVC容器掃描Controller的實例就行。

 

 

然後在一個論壇中得知了是線程的原因:

“因爲主線程中可以直接使用@Autowired註解進行注入,但是在新開的線程中就不可以進行注入,每次啓動服務器就會報空指針異常,新開啓的線程直接就掛掉了,網上也搜了好多,原來是spring不會去管理這個新的線程,所以也就注入不進去任何bean。註解得方式最終都不能注入。

有以下幾種方式來獲取,我使用的是:通過工具類獲取。Spring工具類獲取bean

這種方法必須要把該工具類在SpringApplicationContext中註冊bean,這樣Spring才能通過工具類的set方法給其注入context。這樣也帶出了這種方法的弊端:工具類必須在Spring容器初始化完之後才能工作。

在現有的實現思路的基礎上,這個弊端立刻就顯現出來了,在自己重寫的WebContextListener運行的時候,Spring容器是沒有初始化的!所以會報空指針異常。

解決思路:工具類必須在Spring容器初始化完後纔可以正常工作,那麼可以找一個合適的位置開啓(僅開啓一次)任務調度器。

 

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