現在定時任務服務存在問題,請幫忙核實一下:
現象:定時任務服務器的resin不定時重啟,有時能達到一天一兩次,原因是在創建單例bean時,單例bean正在被銷毀。報錯的類都是RunPickupPathService,每次重啟前都會報如下錯誤。 日志如下:
Caused by: org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'transactionManager': Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
[INFO]2014-08-15 15:46:27 INFO [resin-shutdown] org.springframework.scheduling.concurrent.ExecutorConfigurationSupport.shutdown(150) | Shutting down ExecutorService 'taskExecutor'
<!-- 定時檢查撿貨路徑不完整的, 是否有補貨進來, 如果補貨了,則重新跑撿貨路徑 --> <bean id="xsaCheckUnCompletePathIsSupplied" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <ref bean="xsaCheckUnCompletePathIsSuppliedJobDetail"/> </property> <property name="cronExpression"> <value>${checkUnCompletePathIsSuppliedCron}</value> </property> </bean> <bean id="xsaCheckUnCompletePathIsSuppliedJobDetail" class="springframework.scheduling.quartz.BeanInvokingJobDetailFactoryBean"> <property name="targetBean" value="runPickupPathService" /> <property name="targetMethod" value="checkUnCompletePathIsSupplied" /> </bean> <!-- 對於所有沒有跑的撿貨路徑,進行跑撿貨路徑工作 --> <bean id="xsaRunUnRunPickupPath" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <ref bean="xsaRunUnRunPickupPathJobDetail"/> </property> <property name="cronExpression"> <value>${runUnRunPathCron}</value> </property> </bean> <bean id="xsaRunUnRunPickupPathJobDetail" class="springframework.scheduling.quartz.BeanInvokingJobDetailFactoryBean"> <property name="targetBean" value="autoRunPickupPathService" /> <property name="targetMethod" value="runAllUnRunPickupPath" /> </bean>
這里targetBean autoRunPickupPathService 引用了如下的service,而 runPickupPathService 本身又是定時任務service,在跑完定時任務的時候需要被destory。
@Service public class AutoRunPickupPathService { private final static Logger logger = LoggerFactory.getLogger(RunPickupPathService.class); @Resource private RunPickupPathService runPickupPathService; @Resource private XsaPickupPathMapper xsaPickupPathMapper; /** * 對於所有沒有跑撿貨路徑的單據,跑撿貨路徑, 此方法設置為定時 * @throws Exception */ public void runAllUnRunPickupPath() { synchronized (RunPickupPathService.class) { List<XsaPickupPath> pathList = xsaPickupPathMapper.getAllUnRunPickUpPath(); if(null != pathList && pathList.size() > 0) { for(XsaPickupPath p : pathList) { try { runPickupPathService.runPickupPath(p.getServiceno(), true); } catch (Exception e) { logger.error("Auto Run Pickup Path Error, Transfer NO: " + p.getServiceno() + ", " + e.getMessage()); } } } } } }
出現這種情況是下面情形,按時間先后出現如下 1->2->3->4
1、autoRunPickupPathService 已經運行結束,當前時間只有runPickupPathService 在運行。
2、runPickupPathService 運行完畢,發現此時沒有別的類在引用自己,於是開始執行對bean的銷毀(由spring控制,調用destory方法,不集成spring則由GC回收)。
3、在 runPickupPathService 正在銷毀但銷毀未完成的時候,定時任務 autoRunPickupPathService開始執行,由於類中引用了runPickupPathService ,於是開始創建runPickupPathService的實例。
4、由於spring的bean默認情況下都是單例(singleton),導致出現如上報錯,即 Singleton bean creation not allowed while the singletons of this factory are in destruction 。
最終解釋可以歸為一句話:定時任務的相互調用會導致單例bean出現混亂。
解決方案:去掉定時任務之間的調用。
這是我分析的原因,我檢測的三次重啟都是由這個定時任務創建bean失敗導致。
