`
chongquanyumo
  • 浏览: 30566 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

spring定时任务分析,及其线上实时修改表达式

阅读更多
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();
		}
		
	}
}
分享到:
评论
1 楼 sxshunrj 2016-10-18  
按照你的代码写了一下,一直报找不到字段是为啥呢?
java.lang.NoSuchFieldException: scheduledFutures
at java.lang.Class.getDeclaredField(Class.java:1953)
跟jdk版本有关系吗?请大师指导一下

相关推荐

Global site tag (gtag.js) - Google Analytics