使用spring的定时任务组件的时候,代码如下。
@Scheduled(cron="0 5/5 * * * ?") public void sendWeatherSMS() { String messageContent = messageFactory.getWeatherSMS(); //如果生成短信内容为空的话,则重试3次。 int retryTimes = 3; while(retryTimes>=0&&isEmpty(messageContent)){ logger.error("生成天气信息短信失败。正在进行第"+(4-retryTimes) +"次重试"); try { Thread.sleep(1000*(10- retryTimes)); } catch (InterruptedException e) { // TODO Auto-generated catch block logger.error(e); } messageContent=messageFactory.getWeatherSMS(); retryTimes--; } String phoneNumbers = getSendWeatherInfoPhoneNum().trim(); if(!isEmpty(messageContent)){ foSendSMS.execute(phoneNumbers, messageContent); }else{ logger.error("生成天气信息短信失败。"); } System.out.println("sendWeatherSMS "+phoneNumbers+" "+ messageContent + new Date()); }
忽略掉方法中的,取得内容短信为空后最大重试3次的逻辑。在触发改cron的表达式的时候,发现sendWeatherSMS()方法执行了3次。网上也搜了一些答案, 一开始就是说配置文件文档,tomcat问题,感觉不科学。google一下,发现spring官方文档提供了如下的解释:
Make sure that you are not initializing multiple instances of the same @Scheduled annotation class at runtime, unless you do want to schedule callbacks to each such instance. Related to this, make sure that you do not use @Configurable on bean classes which are annotated with @Scheduled and registered as regular Spring beans with the container: You would get double initialization otherwise, once through the container and once through the @Configurable aspect, with the consequence of each @Scheduled method being invoked twice.
也就是说,造成这个问题的原因在于,自己配置不当或者程序的问题,导致bean被加载了多次。因此解决的办法就是,排除一些Task所在的bean被初始化的地方,避免bean被多次初始化。 我的解决方案是,把schedule的配置文件,单独放到一个xml,避免被多次引用。