CommandQueue
我有一个叫我从 Quartz Job 类引用的 Spring 单例。当作业触发时,它应该在 CommandQueue 中排队命令(调用"write()"
命令使用 Jackson 序列化它,调用"Command.create(String)"
反序列化命令)。
我遇到的问题是 Job 是由 Quartz 实例化的,而不是 Spring,所以我不能@Autowire
在 Job 中使用 CommandQueue,也不能得到对ApplicationContext
. 我也无法将 CommandQueue 传递给作业的构造函数,然后在作业的 JobDataMap 中序列化 CommandQueue,因为当我反序列化 CommandQueue 时,我将创建一个新的 CommandQueue 实例而不是引用单例。
目前我正在使用一种解决方法,其中我从 Job 实例静态引用 CommandQueue 单例,但我想知道是否有一种方法可以在不诉诸静态引用的情况下完成同样的事情。
public abstract class CommandQueue {
protected static CommandQueue queue;
public static CommandQueue queue() { return queue; }
protected CommandQueue() {}
}
@Service("CommandQueue")
@Scope(value = "singleton")
@Profile({"test"})
public class TestQueue extends CommandQueue {
public TestQueue() { CommandQueue.queue = this; }
}
@Service("CommandQueue")
@Scope(value = "singleton")
@Profile({"production"})
public class ProductionQueue extends CommandQueue {
public ProductionQueue() { CommandQueue.queue = this; }
}
@Service
@Scope(value = "singleton")
public class CommandScheduler {
private final org.quartz.Scheduler scheduler;
public CommandScheduler() {
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
}
public JobKey scheduleRecurringSeconds(final Command command, final int seconds) {
JobDetail job = JobBuilder.newJob(CommandJob.class)
.withIdentity(command.getId()).build();
job.getJobDataMap().put("command", command.write());
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(command.getId()).startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(seconds).repeatForever())
.build();
scheduler.scheduleJob(job, trigger);
}
@DisallowConcurrentExecution
public static class CommandJob implements Job {
public void execute(JobExecutionContext context) {
String str = context.getJobDetail().getJobDataMap().get("command");
Command command = Command.create(str);
CommandQueue.queue().enqueue(command);
}
}
}