使用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,避免被多次引用。