2015-07-28 4 views
2

Я использую Dagger 2 в качестве рамки DI, и я предоставляю экземпляр класса Singleton с ним.Как ввести зависимость в задание кварца с помощью Dagger 2

Я также использую планировщик кварца, чтобы назначать задания. Есть ли способ ввести класс singleton в Quartz?

Dagger 2 модуля:

@Module 
public class MyModule { 

    @Provides 
    @Singleton 
      Messager provideMessager() { 

     return new CustomMessager(); 
    } 
} 

Dagger 2 компонента:

@Component(modules = MyModule.class) 
@Singleton 
public interface MyComponent { 

    Messager messager(); 
} 

Кварцевый Работа:

public class MyJob implements Job { 

    // @Inject 
    Messager messager; 

    @Override 
    public void execute(JobExecutionContext context) throws JobExecutionException { 

     messager.sendMessage("Hello."); 
    } 

} 

EDIT

I создали MyJobScheduler класс, который вызывает Кварцевый Работа:

public class MyJobScheduler { 


     public void scheduleJob() { 

      JobDetail myJob = JobBuilder.newJob(MyJob.class) 
              .withIdentity("myJobId", "Group1") 
              .build(); 

      Trigger trigger = TriggerBuilder.newTrigger() 
              .withIdentity("myTriggerId", "Group1") 
              .startNow() 
              .build(); 

       Scheduler scheduler = new org.quartz.impl.StdSchedulerFactory().getScheduler(); 

       scheduler.start(); 


    scheduler.scheduleJob(myJob, trigger); 

    } 
} 

EDIT 2

Так мне удалось настроить его на работу, но я не знаю, если это правильный подход.

Сначала я создал DependencyResolver класс, который я использую в качестве одноэлементных:

public class DependencyResolver { 

    private static DependencyResolver _instance = null; 

    private static MyComponent _myComponent; 

    public static MyComponent getMyComponent() { 
     return _myComponent; 
    } 

    protected DependencyResolver() { 
     // Exists only to defeat instantiation. 
    } 

    public static void initialize() { 

     _myComponent = DaggerMyComponent.builder().build(); 
    } 
} 

Тогда я назвал метод инициализации в методе main:

DependencyResolver.initialize(); 

MyComponent myComponent = DependencyResolver.getMyComponent(); 

И я использовал DependencyResolver в MyJob класса для получения экземпляра Singleton Messager.

public class MyJob implements Job { 

    @Override 
    public void execute(JobExecutionContext context) throws JobExecutionException { 

    MyComponent myComponent = DependencyResolver.getMyComponent(); 

    Messager messager = myComponent.messager(); 
    messager.sendMessage("Hello."); 
    } 
} 

Это правильный способ решить эту проблему? Любой вход будет оценен с большой благодарностью.

+0

Как работа Кварц получить instantia Тед? (где находится 'new MyJob()') –

+0

@ ThorbjørnRavnAndersen См. редактирование. Это очень простая реализация кварца. –

ответ

4

Ваш EDIT 2 DependencyResolver подходит, чтобы подобрать причину, по которой можно использовать Кинжал для инъекции зависимостей, потому что ваша работа получает зависимость от одного провайдера. :-) Это полностью обходит преимущество кинжала, так что вы можете просто иметь синглтон на самой исходной зависимости, например: Messager messager = CustomMessager.getInstance() или что-то в этом роде.

Одна из причин использования Injection Dependency - помочь в тестировании модулей, и в этом случае вы теряете способность высмеивать реализацию Messager в модульном тесте.

Правильный способ использовать инъекции зависимостей с рабочими местами Quartz упоминается в API doc for JobFactory: «Этого интерфейсе может быть полезным для тех, кто хочет, чтобы их экземпляры Job приложений производят с помощью некоторого специального механизма, например, чтобы дать opertunity для зависимая инъекция."

Хитрость заключается в том, чтобы создать свою собственную работу завода, который расширяет SimpleJobFactory и тогда у вас есть возможность инициализировать/впрыснуть зависимости о задании, что-то вроде этого:

public class MyJobFactory extends SimpleJobFactory { 
    private final MyComponent component; 

    @Inject 
    public MyJobFactory(MyComponent component) { 
     this.component = component; 
    } 

    @Override 
    public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException { 
     final Job job = super.newJob(bundle, scheduler); 
     if (job instanceof MyJob) { 
      component.inject((MyJob) job); 
     } 
     return job; 
    } 
} 

И тогда вы говорите планировщик использовать работу завода:

scheduler.setJobFactory(myJobFactory); 

Смотреть полный код here on GitHub

+0

Спасибо за отличный ответ. Репо GitHub - действительно приятный штрих. –

+0

У меня есть несколько вопросов о коде GitHub: 1. Как MyJobFactory чудом впрыскивается в MyJobScheduler, если он не указан в модуле (MyModule). 2. Он не только вводится, но также получает компонент (MyComponent), который также каким-то образом вводится без какого-либо явного положения. Означает ли это, что мы можем вставлять MyComponent везде, где нам нужно, чтобы вручную определять зависимости. 3. Я вижу, что метод MyComponent.inject используется для ввода зависимостей экземпляра. Является ли это стандартной практикой или, скорее, более хакером в этом конкретном случае. –

+0

1. интересное наблюдение - да, я думаю, что это то, что не было широко продемонстрировано или понято в образцах Dagger 2 - вам не нужен метод провайдера для каждой зависимости - вам нужен только модуль, если это зависимость от третьей стороны (без @Inject аннотаций), или если вам нужно инициализировать модуль, например с контекстом активности ... Это уменьшает ненужный шаблон, когда вы это понимаете! :) 2. Да, вы можете вставлять сам компонент, но это можно легко злоупотреблять. 3. Это стандартная практика в этом случае, потому что задание создается извне, так что это единственный способ ввести свои поля. –

Смежные вопросы