这是我的代码:
@Scheduled(cron = "30 3 * * * *")
public void myCron() {
//we don't care what we do here
}
我想知道是否可以自动在@Scheduled
添加跟踪ID(或其他信息)。
每次触发@Scheduled
时,ID都会有所不同。
我想这样做是为了避免重复代码,如:
@Scheduled(cron = "10 3 * * * *")
public void myCron() {
MDC.put("myId", UUID.randomUUID().toString());
//we don't care what we do here
}
@Scheduled(cron = "30 3 * * * *")
public void mySecondCron() {
MDC.put("myId", UUID.randomUUID().toString());
//we don't care what we do here
}
我厌倦了实施SchedulingConfigurer
,但SchedulingConfigurer#configureTasks
太晚了,因为已经创建了任务(runnable),因此添加了tak的行为
由于
答案 0 :(得分:2)
您可以尝试实施自定义TaskScheduler
并在SchedulingConfigurer.configureTasks
中注册。 ConcurrentTaskScheduler
可以作为一个例子。不幸的是,这个类没有很好地设计继承,否则decorateTask
方法将受到保护。所以你需要覆盖所有方法,用你的逻辑添加一个额外的Runnable装饰器。像这样的东西:
@Configuration
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {
public static class MyTaskScheduler extends ConcurrentTaskScheduler {
public MyTaskScheduler() {
}
public MyTaskScheduler(ScheduledExecutorService scheduledExecutor) {
super(scheduledExecutor);
}
public MyTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
super(concurrentExecutor, scheduledExecutor);
}
// TODO override other methods
@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return super.schedule(decorateTask(task), trigger);
}
private Runnable decorateTask(Runnable task) {
// not 100% sure about safety of this cast
return new MyRunnable((ScheduledMethodRunnable) task);
}
private static class MyRunnable implements Runnable {
private final ScheduledMethodRunnable runnable;
private final AtomicLong counter = new AtomicLong();
public MyRunnable(ScheduledMethodRunnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
System.out.println(runnable.getMethod().toGenericString() + " " + counter.incrementAndGet());
runnable.run();
}
}
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
TaskScheduler taskScheduler = new MyTaskScheduler(Executors.newScheduledThreadPool(10));
taskRegistrar.setTaskScheduler(taskScheduler);
}
@Scheduled(cron = "0/1 * * * * *")
public void test() {
System.out.println("Running task in thread " + Thread.currentThread().getId());
}
}
答案 1 :(得分:0)
在AOP进入用@Scheduled
注释的任何方法并设置MDC之前,您还可以使用AOP拦截代码。出于良好的考虑,它会在退出该方法时清除MDC。
请注意atExecutionTimeInMyNamespace
切入点,您可以选择在其中放置自己的包命名空间,以限制仅在自己的代码中使用@Scheduled(即,在任何第三方库中都不使用@Scheduled,但是不太可能是)。
@Aspect
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ScheduledTaskTracingAspect {
@Pointcut("@annotation(org.springframework.scheduling.annotation.Scheduled)")
public void methodAnnotatedWithScheduled() {}
@Pointcut("execution(* com.mycompany..*(..))")
public void atExecutionTimeInMyNamespace() {}
@Around("methodAnnotatedWithScheduled() && atExecutionTimeInMyNamespace()")
public Object connectionAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
MDC.put("myId", UUID.randomUUID().toString());
try {
return joinPoint.proceed();
}
finally {
// Might as well clear all the MDC, not just the "myId"
MDC.clear();
}
}
}