ищу постоянные таймеры для весеннего применения - PullRequest
2 голосов
/ 20 сентября 2011

Я ищу библиотеку, которая позволяет мне делать

  1. определить работника, который будет вызываться один раз в определенное время в будущем (не требуется переупорядочение / cron-подобный подвиг), т.е. таймер
  2. Работник должен принять контекст с некоторыми параметрами / входами
  3. все должно быть постоянным в БД (или файле) рабочего
  4. Работник должен управляться весной - весна должна создавать экземпляр работника, чтобы в него можно было вводить зависимости
  5. иметь возможность динамически создавать таймеры с помощью API, а не только статически с помощью пружинных XML-компонентов

приятно иметь:

  1. поддерживает кластер, т.е. имеет несколько узлов, на которых может размещаться работник. каждое хранилище заданий в БД будет вызывать ОДНУ работу на одном из узлов

Я рассмотрел несколько альтернатив, ни один из которых не соответствует требованиям:

  • Кварц

при использовании org.springframework.scheduling.quartz.JobDetailBean заставляет кварц создавать ваш рабочий экземпляр (а не к весне), чтобы вы не могли получить инъекцию зависимости (что приведет меня к использованию Service Locator, которого я хочу избежать)

при использовании org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean вы не можете получить контекст. ваш Worker предоставляет один открытый метод, который не принимает аргументов. Кроме того, при использовании MethodInvokingJobDetailFactoryBean вы не можете использовать постоянство (формировать Javadoc)

Примечание: JobDetails, созданные с помощью этого FactoryBean, не сериализуются и поэтому не подходят для постоянных хранилищ заданий. Вам нужно реализовать свое собственное Кварцевое задание в качестве тонкой оболочки для каждого случая, когда вы хотите, чтобы постоянное задание передавалось определенному методу обслуживания.

  • Таймер Spring и простые JDK-таймеры не поддерживают функцию сохранения / кластеризации

Я знаю, что могу сам себя использовать, используя DB и Spring (или даже JDK) таймеры, но для этого я предпочитаю использовать стороннюю библиотеку.

Есть предложения?

Ответы [ 3 ]

4 голосов
/ 21 сентября 2011

Если вы хотите создать сведения о задании для генерации триггеров / сведений о задании во время выполнения и при этом иметь возможность использовать Spring DI для своих компонентов, вы можете обратиться к этому сообщению в блоге , в нем показано, как использовать SpringBeanJobFactory в сочетании с ObjectFactoryCreatingFactoryBean для создания триггерных объектов Quartz во время выполнения с бобами, добавленными Spring.

0 голосов
/ 19 декабря 2015

Для тех, кто заинтересован в альтернативе Quartz, взгляните на db-scheduler (https://github.com/kagkarlsson/db-scheduler).. Постоянное расписание задачи / выполнения хранится в одной таблице базы данных. Гарантируется, что оно будет выполнено только один разпланировщик в кластере.

  1. Да, см. пример кода ниже.

  2. В настоящее время ограничен одним строковым идентификатором без ограничения формата.в будущем планировщик, вероятно, будет расширен за счет лучшей поддержки подробностей / параметров задания.

  3. Время выполнения и контекст постоянны в базе данных. Привязка имени задачи к работникувыполняется при запуске планировщика. Spring может быть создан для рабочего при условии, что он реализует интерфейс ExecutionHandler.

  4. См. 3).

  5. Да, см. Пример кода ниже.

Пример кода:

private static void springWorkerExample(DataSource dataSource, MySpringWorker mySpringWorker) {

    // instantiate and start the scheduler somewhere in your application
    final Scheduler scheduler = Scheduler
            .create(dataSource)
            .threads(2)
            .build();
    scheduler.start();

    // define a task and a handler that named task, MySpringWorker implements the ExecutionHandler interface
    final OneTimeTask oneTimeTask = ComposableTask.onetimeTask("my-onetime-task", mySpringWorker);

    // schedule a future execution for the task with a custom id (currently the only form for context supported)
    scheduler.scheduleForExecution(LocalDateTime.now().plusDays(1), oneTimeTask.instance("1001"));
}


public static class MySpringWorker implements ExecutionHandler {
    public MySpringWorker() {
        // could be instantiated by Spring
    }

    @Override
    public void execute(TaskInstance taskInstance, ExecutionContext executionContext) {
        // called when the execution-time is reached
        System.out.println("Executed task with id="+taskInstance.getId());
    }
}
0 голосов
/ 20 сентября 2011

Ваши требования 3 и 4 на самом деле не имеют смысла для меня: как вы можете сериализовать весь пакет (рабочий + рабочий) и заставить его волшебным образом проснуться и выполнить свою работу?Разве что-то в вашей работающей системе не должно делать это в нужное время?Разве это не должен быть рабочий в первую очередь?

Мой подход был бы таков: создайте таймер, в который Spring может создавать экземпляры и внедрять зависимости.Затем этот таймер будет загружать свои работы / задачи из постоянного хранилища, планировать их выполнение и выполнять.Ваш класс может быть обёрткой около java.util.Timer и вообще не заниматься планированием.Вы должны реализовать логику, связанную с кластеризацией, чтобы только один Таймер / Работник мог выполнять работу / задачу.

...