现在定时任务服务存在问题,请帮忙核实一下:
现象:定时任务服务器的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失败导致。