Blog

Quarz und Frühling

Maarten Winkels

Aktualisiert Oktober 23, 2025
5 Minuten

Quartz ist ein Java Framework für die Zeitplanung. Es ermöglicht Anwendungen, Aufgaben für die Ausführung in der Zukunft zu planen. Spring ist ein Java IoC-Container. Er hilft dabei, die Komponenten, aus denen eine Anwendung besteht, zusammenzufügen. In diesem Blog erfahren Sie, wo die beiden sich treffen und wie sie zusammenarbeiten können, um die Entwicklung Ihrer Anwendung zu erleichtern.

Parametrisierte Jobs Quartz basiert auf den Konzepten von Jobs und Triggern. Ein Job ist eine Aufgabe, die ausgeführt wird, wenn ein zugehöriger Auslöser ausgelöst wird. Oft sind Jobs parametrisiert; sie verwenden bestimmte Eingabeparameter, die bestimmen, wie die Aufgabe ausgeführt wird. Quartz verwendet eine JobDataMap, die Schlüssel-Wert-Paare enthält, die Ihre Job-Implementierung verwenden kann. Die Map wird an die Methode org.quartz.Job.execute(JobExecutionContext) übergeben (die im JobExecutionContext gekapselt ist) und Ihr Job muss wissen, welche Schlüssel er verwenden muss, um die von ihm verwendeten Parameterwerte zu finden. Spring ist es gewohnt, Werte auf JavaBeans zu setzen, die auf einer bestimmten Konfiguration basieren. Um die Aufgabe zu vereinfachen, einen Quartz-Job zu schreiben, enthält Spring eine Implementierung von org.quartz.Job, die genau das tut: Er verwendet die Schlüssel-Wert-Paare in der JobDataMap, um JavaBean-Eigenschaften für sich selbst festzulegen. Um diese Funktionalität zu nutzen, müssen Sie die Klasse org.springframework.scheduling.quartz.QuartzJobBean erweitern, Ihre Implementierung der Methode execute(JobExecutionContext) in die Methode executeInternal(JobExecutionContext) verschieben und Setter für alle Parameter erstellen, die Ihr Job verwendet. Das Beispielprojekt, das diesem Blog beigefügt ist, enthält einen PrinterJob, der sehr einfach ist.

public class PrinterJob extends QuartzJobBean {
  protected String Nachricht;
  @Override
  protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
  System.out.println(Nachricht);
  }
  public void setMessage(String message) {
  this.message = Nachricht;
  }
}

Dieser Auftrag gibt nur eine Nachricht auf der Konsole aus. Die Nachricht ist ein Parameter für den Auftrag. Woher bezieht der Auftrag seine Nachricht? Er verwendet die JobDataMap, aber nicht direkt, sondern über die Funktionen seiner Superklasse, um seine Eigenschaften festzulegen. Um eine bestimmte Nachricht für den Druck zu planen, wird das folgende Fragment verwendet.

private void scheduleJob(String message, Class clazz, SimpleTrigger trigger) {
  JobDetail jobDetail = new JobDetail(Nachricht, "MSG", clazz);
  JobDataMap map = new JobDataMap();
  map.put("Nachricht", Nachricht);
  jobDetail.setJobDataMap(map);
  scheduler.scheduleJob(jobDetail, trigger);
}

SimpleTrigger, JobDetail und JobDataMap sind die Quarz-Infrastruktur, die die eigentliche Planung durchführt. Der Scheduler ist eine org.quartz.Scheduler-Instanz, die Hauptkomponente von Quartz. Der wichtigste Teil hier ist der Schlüssel, der zum Speichern der Nachricht in der JobDataMap verwendet wird. Dieser muss mit dem Eigenschaftsnamen Ihrer Job Bean übereinstimmen. Da die Setter-Methode in diesem Fall "setMessage" heißt, ist der zu verwendende Schlüssel "message". Ihre Job-Implementierung muss sich nicht mehr um die Job-Data-Map kümmern und kann einfach deren Eigenschaften verwenden. Dies ist ein weiteres Beispiel für eine "Umkehrung der Kontrolle". Dienste und Ressourcen In einer J2EE-Umgebung muss Ihr Auftrag oft Dienste oder Ressourcen verwenden, die nicht einfach serialisiert werden können. Quartz kann nicht serialisierbare Objekte in seiner JobDataMap speichern, aber nur, wenn der Zeitplan nicht persistent ist. Wenn Ihr Zeitplan robust sein muss, können Sie einen persistenten JobStore verwenden. Um einen solchen JobStore zu verwenden, müssen alle Daten in Ihrer JobDataMap serialisierbar sein. Um dies zu ermöglichen, verfügt ein Quartz Scheduler über einen SchedulerContext, eine weitere Map, die Dienste und Ressourcen als Werte enthalten kann. Da Sie Spring verwenden, sind alle Ihre Dienste und Ressourcen in Ihrem ApplicationContext definiert. Ihr Quartz Scheduler kann in diesem Kontext auch mit org.springframework.scheduling.quartz.SchedulerFactoryBean konfiguriert werden. Diese Factory Bean verfügt über eine praktische Methode zum Einrichten des SchedulerContextes.

  



  ...
    

 

Die obige Konfiguration fügt den heavyService zum SchedulerContext hinzu. Ein Job, der diesen Dienst nutzt, kann diesen Dienst nun mit dem richtigen Schlüssel aus dem JobExecutionContext abrufen. Die QuartzJobBean-Implementierung von Springs sucht auch im SchedulerContext nach Werten, wenn Sie die Eigenschaften der Jobbean festlegen. Das macht Ihre Implementierung sehr viel einfacher.

public class ServicePrinterJob extends PrinterJob {
  private HeavyService heavyService;
  @Override
  protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
  heavyService.doPrint(Nachricht);
  }
  public void setHeavyService(HeavyService heavyService) {
  this.heavyService = heavyService;
  }
}

Jetzt wird die Eigenschaft heavyService aus dem SchedulerContext geholt und die Eigenschaft message aus der JobDataMap. All dies geschieht außerhalb des Anwendungsbereichs Ihrer Implementierung. Zirkuläre Referenzen Oftmals wird durch die Planung eine zirkuläre Referenz zwischen Beans in Ihrem Kontext eingeführt. Ein Dienst, der für eine bestimmte Aufgabe verwendet wird, wird in manchen Fällen Aufgaben für sich selbst mithilfe eines Quartz Schedulers planen. Spring kann mit zirkulären Referenzen umgehen, solange Sie Setter-Injection verwenden und über Lazy Beans verfügen. Standardmäßig ist die SchedularFactoryBean nicht lazy, was zu einer BeanCreationException führt, wenn der Anwendungskontext geladen wird. Wenn Sie die Bean so einstellen, dass sie träge initialisiert wird, ist dieses Problem gelöst. Die folgende Konfiguration wird nur aufgrund dieser Eigenschaft geladen.

  


  ...

    

 

In diesem Fall wird eine Methode des RecursiveService aufgerufen, die einen Auftrag plant, der wiederum den RecursiveService verwendet. Fazit Die Quartz-Spring-Integration macht das Schreiben von Quartz-Aufträgen für eine Spring-Anwendung wirklich einfach. Der Code, den Sie schreiben müssen, ist sehr einfach und prägnant und sehr leicht zu testen. Die Spring-Konfiguration ist nicht komplex.

Verfasst von

Maarten Winkels

Contact

Let’s discuss how we can support your journey.