在Spring中访问计划任务



我在Spring的任务调度程序:

中安排了几个任务
<task:scheduled-tasks>
    <task:scheduled ref="task1" method="run"
        cron="0 0 */0 * * *" />
    <task:scheduled ref="task2" method="run"
        cron="0 0 */30 * * *" />
</task:scheduled-tasks>
<task:scheduler id="scheduler" pool-size="10" />

如何访问计划任务列表并从应用程序上下文中检索元信息(例如下一次执行时间)?

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
ThreadPoolTaskScheduler scheduler = (ThreadPoolTaskScheduler)context.getBean("scheduler");
//... how to continue from here?

Spring中没有这样的公共API。

相关:

  • Spring 在运行时表示的对象?

我刚刚弄明白了

从这个开始,得到计划的内容。

    ThreadPoolTaskScheduler xScheduler = (ThreadPoolTaskScheduler)this.taskScheduler;
    ScheduledThreadPoolExecutor xService = (ScheduledThreadPoolExecutor)xScheduler.getScheduledExecutor();
    BlockingQueue<Runnable> queue = xService.getQueue();
    Object[] scheduledJobs = queue.toArray();

如果这个数组查看调试器中的实例,找出你需要的。

然后像这样编写反射代码来获取Spring和Java中隐藏的API。请参阅可访问的设置,这是获得这些私有项目的唯一方法。您可能需要使用不同的公共类来获取某些私有字段,请查看api文档并在eclipse中查看这些类的源代码。

            Method delayM = obj.getClass().getDeclaredMethod("getDelay", TimeUnit.class);
            delayM.setAccessible(true);
            // delayM = obj.getClass().getDeclaredMethod("getDelay", TimeUnit.class);
            Long delay = (Long)delayM.invoke(obj, new Object[] { tu } );

触发器和根runnable在这个对象的callable字段中,rescheulingrunnable的实例不是一个公共类,问Spring为什么他们这样做。你可以通过反射从DelegatingErrorHandlingRunnable中获得委托。

@Randy Poznan的回答已经很好了,但是它使用了不必要的反射,delayM.setAccessible(true)可能会导致Java 17的问题,并且它的更严格的访问规则(运行时异常!)。

一个没有反射的解决方案是:

// Bean is named "taskScheduler" now
ThreadPoolTaskScheduler taskScheduler = (ThreadPoolTaskScheduler) context.getBean("taskScheduler");
ScheduledThreadPoolExecutor scheduledExecutor =
    (ScheduledThreadPoolExecutor) taskScheduler.getScheduledExecutor();
BlockingQueue<Runnable> queue = scheduledExecutor.getQueue();
if (queue.isEmpty()) {
    return null;
} else {
    for (Runnable runnable : queue) {
        // This is it: Casting to `ScheduledFuture`.
        var scheduledFuture = (ScheduledFuture) runnable;
        final long delay = scheduledFuture.getDelay(TimeUnit.MINUTES);
        System.out.println("Delay: " + delay + " on runnable: " + runnable);
    }
}

最新更新