本文参考了博客网的博文《spring + quartz 定时器实现》,该博文地址为
原博文使用的是Quartz 2.X以下的版本,我使用的是Quartz 2.2.1版本,Spring版本请使用3.1以上的版本。
原博文Cron表达式是配置在方法级别的@interface上面,一个方法只能使用相同的Cron表达式,我把Cron表达式放在方法@interface上,个人觉得更符合实际,这样同一个类上面可以配置多个不同时间运行的定时器。下面是代码:
首先定义注解:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyTriggerType {
String value() default "";
}
方法层面的注解:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyTriggerMethod {
/** 定义定时器触发时间 */
String cronExpression() default "";
}
Job类:
@MyTriggerType
public class MyAnnoJob {
@MyTriggerMethod(cronExpression = "0/1 * * * * ?")
public void execute() {
System.out.println("定时任务,每秒执行一次----------------");
}
@MyTriggerMethod(cronExpression = "0/3 * * * * ?")
public void execute2() {
System.out.println("定时任务,每三秒执行一次----------------");
}
}
重新SchedulerFactoryBean类:
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
public class MyTriggerSchedulerFactoryBean extends SchedulerFactoryBean {
/** 日志 */
protected Log log = LogFactory.getLog(MySchedulerFactoryBean.class
.getName());
/** Spring 上下文 */
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void registerJobsAndTriggers() throws SchedulerException {
try {
// 获取所有bean name
String[] beanNames = applicationContext
.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
Class> targetClass = applicationContext.getType(beanName);
// 循环判断是否标记了MyTriggerType注解
if (targetClass.isAnnotationPresent(MyTriggerType.class)) {
Object targetObject = applicationContext.getBean(beanName);
// 获取时间表达式
String cronExpression = "";
String targetMethod = "";
MyTriggerMethod triggerMethod = null;
// 确定标记了MyTriggerMethod注解的方法名
Method[] methods = targetClass.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MyTriggerMethod.class)) {
targetMethod = method.getName();
triggerMethod = (MyTriggerMethod) method
.getAnnotation(MyTriggerMethod.class);
cronExpression = triggerMethod.cronExpression();
// 注册定时器业务类
registerJobs(targetObject, targetMethod, beanName,
cronExpression);
}
}
}
}
} catch (Exception e) {
log.error(e);
}
}
/**
* 注册定时器
*
* @param targetObject
* @param targetMethod
* @param beanName
* @param cronExpression
* @throws Exception
*/
private void registerJobs(Object targetObject, String targetMethod,
String beanName, String cronExpression) throws Exception {
// 声明包装业务类
MethodInvokingJobDetailFactoryBean jobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
jobDetailFactoryBean.setTargetObject(targetObject);
jobDetailFactoryBean.setTargetMethod(targetMethod);
jobDetailFactoryBean.setBeanName(beanName + "_" + targetMethod
+ "_Task");
jobDetailFactoryBean.setName(beanName + "_" + targetMethod + "_Task");
jobDetailFactoryBean.setConcurrent(false);
jobDetailFactoryBean.afterPropertiesSet();
//System.out.println(beanName + "_" + targetMethod+"-----cron=" + cronExpression);
// 获取JobDetail
JobDetail jobDetail = jobDetailFactoryBean.getObject();
// 声明定时器
CronTriggerFactoryBean cronTriggerBean = new CronTriggerFactoryBean();
cronTriggerBean.setJobDetail(jobDetail);
cronTriggerBean.setCronExpression(cronExpression);
cronTriggerBean.setName(beanName + "_" + targetMethod + "_Trigger");
cronTriggerBean.setBeanName(beanName + "_" + targetMethod + "_Trigger");
cronTriggerBean.afterPropertiesSet();
CronTrigger trigger = cronTriggerBean.getObject();
;
// 将定时器注册到factroy
List triggerList = new ArrayList();
triggerList.add(trigger);
Trigger[] triggers = (Trigger[]) triggerList
.toArray(new Trigger[triggerList.size()]);
setTriggers(triggers);
super.registerJobsAndTriggers();
}
}
quartz配置:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
测试方法:
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.quartz.SchedulerException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
public class TestAnnoTrigger {
ApplicationContext context;
public static void main(String[] args) throws Exception {
TestAnnoTrigger t=new TestAnnoTrigger();
t.TestMyCron();
}
public void TestMyCron() throws Exception{
context=new ClassPathXmlApplicationContext("classpath:config/myquartz-annoconfig.xml");
TimeUnit.MINUTES.sleep(2);
}
}
没有使用Junit原因是我的电脑点击Run As Junit Test半天没反应,只好这样写了。
全文完。