1. 根据配置文件 创建ScheduledTaskRegistrar 对象之后,
TaskScheduler taskScheduler 任务池 已有值;
Map<Runnable, String> cronTasks 计划任务map,key为任务对象,value为定时表达式
Set<ScheduledFuture<?>> scheduledFutures = new LinkedHashSet<ScheduledFuture<?>>(); 被创建
2.ScheduledTaskRegistrar.afterPropertiesSet()被执行
根据 cronTasks 创建 ScheduledFuture 放入 scheduledFutures 中
如下:
for (Map.Entry<Runnable, String> entry : this.cronTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.schedule(entry.getKey(), new CronTrigger(entry.getValue())));
}
(1)创建ScheduledFuture 是通过创建ReschedulingRunnable 对象调用对应的 schedule() 方法来完成。
(2)在 ReschedulingRunnable . schedule() 中,根据表达式计算当前任务下次执行时间,然后将this, 也就是ReschedulingRunnable对象本身,
交由 taskScheduler 任务池 去执行。
(3)任务池到时执行 ReschedulingRunnable 对象的run方法,记录开始执行的时间和 调用supper.run()后的结束时间,用这两个时间修改triggerContext;
因为 ReschedulingRunnable 对象在创建的时候,已将业务方法的执行代理,给了 supper的delegate属性,所以supper.run()执行的时候其实就是
执行 delegate.run() 方法,也就是执行业务方法;
ScheduledMethodRunnable 类只有两个属性,一个是业务对象,一个是要执行的方法;然后在run方法中就是用反射 执行业务对象的 对应方法而已。
获取一个类的方法对象 getClass().getMethod(methodName); 即可;
动态修改指定定时任务表达式,代码如下:
public class AuditDefectServiceTest {
public static void main(String[] args){
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext("classpath:test-context.xml");
appContext.start();
try {
System.out.println("start..");
Thread.sleep(1000*4);
System.out.println("end...");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//appContext.refresh();
ScheduledTaskRegistrar s = appContext.getBean(ScheduledTaskRegistrar.class);
try {
Field f = s.getClass().getDeclaredField("scheduledFutures");
ReflectionUtils.makeAccessible(f);
Set<ScheduledFuture<?>> rt = (Set<ScheduledFuture<?>>) ReflectionUtils.getField(f, s);
for (ScheduledFuture<?> it : rt){
Field f2 = it.getClass().getDeclaredField("trigger");
ReflectionUtils.makeAccessible(f2);
CronTrigger trigger = (CronTrigger) ReflectionUtils.getField(f2, it);
Field f3 = trigger.getClass().getDeclaredField("sequenceGenerator");
ReflectionUtils.makeAccessible(f3);
ReflectionUtils.setField(f3, trigger, new CronSequenceGenerator("0/2 * * 5-29 * ?", TimeZone.getDefault()));
Method scheduleMethod = it.getClass().getDeclaredMethod("schedule");
ReflectionUtils.makeAccessible(scheduleMethod);
ReflectionUtils.invokeMethod(scheduleMethod, it);
}
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}