Quartz использует объекты Trigger, Job и JobDetail для реализации планирования всех видов задач. Об основных понятиях, лежащих в основе Quartz, см. на сайте Quartz. Для обеспечения удобства Spring предусматривает несколько классов, которые упрощают использование Quartz в приложениях на базе Spring.

Использование JobDetailFactoryBean

Объекты JobDetail из Quartz содержат всю информацию, необходимую для выполнения задачи. Spring предусматривает JobDetailFactoryBean, который предоставляет свойства в стиле бинов для целей конфигурации XML. Рассмотрим следующий пример:

<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="example.ExampleJob"/>
    <property name="jobDataAsMap">
        <map>
            <entry key="timeout" value="5"/>
        </map>
    </property>
</bean>

Конфигурация детализации задачи содержит всю информацию, необходимую для выполнения задачи (ExampleJob). Врем ожидания указывается в карте данных задачи. Карта данных задачи доступна через JobExecutionContext (передается вам во время выполнения), но JobDetail также получает свои свойства из данных задачи, отображенных на свойства экземпляра задачи. Так, в следующем примере ExampleJob содержит свойство бина с именем timeout, а в JobDetail оно применяется автоматически:

package example;
public class ExampleJob extends QuartzJobBean {
    private int timeout;
    /**
     * Сеттер, вызываемый после создания экземпляра ExampleJob,
     * со значением из JobDetailFactoryBean (5)
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
    protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
        // выполняем фактическую работу
    }
}

Вам также доступны любые дополнительные свойства из карты данных задачи.

При помощи свойств name и group можно изменить имя и группу задачи соответственно. По умолчанию имя задачи совпадает с именем бина JobDetailFactoryBean(exampleJob в предыдущем примере выше).

Использование MethodInvokingJobDetailFactoryBean

Зачасту требуется просто вызвать метод для определенного объекта. Используя MethodInvokingJobDetailFactoryBean, можно сделать именно это, как показано в следующем примере:

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="exampleBusinessObject"/>
    <property name="targetMethod" value="doIt"/>
</bean>

Предыдущий пример приводит к тому, что метод doIt вызывается для метода exampleBusinessObject, как показано в следующем примере:

public class ExampleBusinessObject {
    // свойства и взаимодействующие объекты
    public void doIt() {
        // выполняем фактическую работу
    }
}
<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>

При использовании MethodInvokingJobDetailFactoryBean не требуется создавать однострочные задачи, которые лишь вызывают метод. Требуется лишь создать реальный бизнес-объект и связать с объектом детализации.

По умолчанию задачи в Quartz не имеют статического характера, что приводит к тому, что задачи могут мешать друг другу. Если вы зададите два триггера для одного и того же класса JobDetail, возможно, что до завершения первой задачи начнется вторая. Если классы JobDetail реализуют интерфейс Stateful, то этого не происходит. Вторая задача не начинается до завершения первой. Для того чтобы задачи, получаемые от MethodInvokingJobDetailFactoryBean, не выполнялись параллельно, установите флаг concurrent в false, как показано в следующем примере:

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="exampleBusinessObject"/>
    <property name="targetMethod" value="doIt"/>
    <property name="concurrent" value="false"/>
</bean>
По умолчанию задачи будут выполняться параллельно.

Связывание задач с помощью триггеров и SchedulerFactoryBean

Мы создали детализацию задачи и задачи. Мы также рассмотрели вспомогательные бины, которые позволяют вызывать метод для определенного объекта. Конечно, нам все еще нужно составить расписание самих задач. Для этого используются триггеры и SchedulerFactoryBean. В Quartz доступно несколько триггеров, а Spring предусматривает две реализации FactoryBean для Quartz с удобными настройками по умолчанию: CronTriggerFactoryBean и SimpleTriggerFactoryBean.

Триггеры должны быть запланированы. Spring предлагает SchedulerFactoryBean, который открывает триггеры для настройки в качестве свойств. SchedulerFactoryBean планирует фактические задания с этими триггерами.

В следующем листинге используются как SimpleTriggerFactoryBean, так и CronTriggerFactoryBean:

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    <!-- see the example of method invoking job above -->
    <property name="jobDetail" ref="jobDetail"/>
    <!-- 10 секунд -->
    <property name="startDelay" value="10000"/>
    <!-- повторяем каждые 50 секунд... -->
    <property name="repeatInterval" value="50000"/>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="exampleJob"/>
    <!-- выполняем каждое утро в 6 утра... -->
    <property name="cronExpression" value="0 0 6 * * ?"/>
</bean>

В предыдущем примере установлены два триггера: один запускается каждые 50 секунд с начальной задержкой в 10 секунд, а другой запускается каждое утро в 6 часов утра. Чтобы завершить все, нам нужно установить SchedulerFactoryBean, как показано в следующем примере:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="cronTrigger"/>
            <ref bean="simpleTrigger"/>
        </list>
    </property>
</bean>

Для SchedulerFactoryBean доступны дополнительные свойства, такие как календари, используемые детализацией задачи, свойства для настройки Quartz и DataSource из JDBC, передаваемый Spring. Дополнительную информацию см. в javadoc по SchedulerFactoryBean.

SchedulerFactoryBean также распознает файл quartz.properties в classpath, основываясь на ключах свойств Quartz, как и при обычной конфигурации Quartz. Обратите внимание, что многие настройки SchedulerFactoryBean взаимодействуют с общими настройками Quartz в файле свойств; поэтому не рекомендуется задавать значения на обоих уровнях. Например, не устанавливайте свойство "org.quartz.jobStore.class", если хотите использовать DataSource, предоставляемый Spring, или задайте вариант org.springframework.scheduling.quartz.LocalDataSourceJobStore, который является полноценной заменой стандартного org.quartz.impl.jdbcjobstore.JobStoreTX.