spring3.0基于注解的定时器以及执行两次的解决办法

时间:2023-01-31 23:34:11

参考:

http://www.kaifajie.cn/spring/7250.html

http://hi.baidu.com/hi_hi/item/db31126fb5916891c4d2494b

 

配置文件:

1.首先要在application-context.xml里面配置好namespace 和schema,如下:

 

xmlns:task="http://www.springframework.org/schema/task"

 


http://www.springframework.org/schema/task
 http://www.springframework.org/schema/task/spring-task-3.0.xsd

 

2.在application-context.xml里面配置<task:annotation-driven/>,加下面一行就行:

<task:annotation-driven/>

 

<!-- The <task:annotation-driven/> element sets Spring up to automatically support
    scheduled and asynchronous methods. These methods are identified with the
    @Scheduled and @Async methods, respectively -->

 

 

 

例如:

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:task="http://www.springframework.org/schema/task"
    xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.0.xsd
                        http://www.springframework.org/schema/task
                        http://www.springframework.org/schema/task/spring-task-3.0.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <task:executor id="executor" pool-size="5"/>
 <task:scheduler id="scheduler" pool-size="10"/>
    <task:annotation-driven executor="executor" scheduler="scheduler"/>

 

 

 

3.在Bean里面的调度方法加注解@Scheduled,其中@Scheduled的attribute有三种:  

  (1)fixedRate:每隔多少毫秒执行一次该方法。如:

Java代码 
@Scheduled(fixedRate=2000)  
public void scheduleMethod(){  
    System.out.println("Hello world...");  
}  
     

  

  (2)fixedDelay:当一次方法执行完毕之后,延迟多少毫秒再执行该方法。 

  (3)cron:详细配置了该方法在什么时候执行。cron值是一个cron表达式。如:

Java代码 
@Scheduled(cron="0 0 0 * * SAT")  
public voidarchiveOldSpittles(){  
// ...  

 

 


一些cron表达式的例子:


Cron expression        What it means
0 0 10,14,16 * * ?       Every day at 10 a.m., 2 p.m., and 4 p.m.
0 0,15,30,45 * 1-30 * ?    Every 15 minutes on the first 30 days of the month
30 0 0 1 1 ? 2012       30 seconds after midnight on January 1, 2012
0 0 8-17 ? * MON-FRI     Every working hour of every business day

 

 

 

在spring3 中的task 命名空间。可以部分去取代 quartz,并且支持注解方式。但是如果使用更加复杂的任务调度。还是建议是使用quartz。

  • 使用 注解来 来调度任务

 

注意其中的@Scheduled 标签

配置spring的applicationContext.xml

 

 <task:executor id="executor" pool-size="1" />
 <task:scheduler id="scheduler" pool-size="3" />
 <!-- 定时器开关-->
 <task:annotation-driven executor="executor" scheduler="scheduler" />

 

 

最近用Spring的基于注解定时器的时候,发现到时间后,任务总是重复执行两次,在tomcat或jboss下都如此。
打印出他们的hashcode,发现是不一样的,也就是说,在web容器启动的时候,重复启了两个定时线程。
研究下来发现确实会加载两次:
第一次:web容器启动的时候,读取applicationContext.xml文件时,会加载一次。
第二次:Spring本身会加载applicationContext.xml一次。
而我的定时器配置就是写在applicationContext.xml文件里的。

解决办法很简单
先把定时器配置信息提取出来,单独存成一个文件,比如applicationContext-quartz.xml
然后修改web.xml,让web容器启动时,可以加载该文件

这样quartz只会在web容器启动时加载一次,Spring不会再加载了。