定时任务服务器不定时重启原因解析

现在定时任务服务存在问题,请帮忙核实一下:
 
现象:定时任务服务器的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失败导致。
原文地址:https://www.cnblogs.com/seanvon/p/3919863.html