【问题标题】:How to inject dependency in a Quartz job using Dagger 2如何使用 Dagger 2 在 Quartz 作业中注入依赖项
【发布时间】:2015-07-28 08:28:03
【问题描述】:

我使用 Dagger 2 作为我的 DI 框架,并提供了一个单例类实例。

我也使用 Quartz Scheduler 来安排作业。有没有办法将单例类注入到 Quartz 作业中?

匕首 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.");
    }

}

编辑

我创建了一个调用 Quartz Job 的 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);

    }
}

编辑 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方法中调用了initialize方法:

DependencyResolver.initialize();

MyComponent myComponent = DependencyResolver.getMyComponent();

我在 MyJob 类中使用了 DependencyResolver 来获取 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.");
    }
}

这是解决此问题的正确方法吗?任何意见将不胜感激。

【问题讨论】:

  • Quartz 作业如何实例化? (new MyJob() 在哪里)
  • @ThorbjørnRavnAndersen 查看编辑。这是一个非常基本的 Quartz 实现。

标签: java quartz-scheduler dagger-2


【解决方案1】:

您的 EDIT 2 DependencyResolver 方法有点挫败使用 Dagger 注入依赖项的全部原因,因为您的工作从单例提供程序获取依赖项。 :-) 它完全绕过了 Dagger 的好处,所以你还不如在源依赖本身上有一个单例,比如:Messager messager = CustomMessager.getInstance() 或类似的东西。

使用依赖注入的一个原因是为了协助进行单元测试,在这种情况下,您将失去在单元测试中模拟 Messager 实现的能力。

API doc for JobFactory 中提到了使用 Quartz 作业的依赖注入的正确方法:“这个接口可能对那些希望他们的应用程序通过一些特殊机制生成 Job 实例的人有用,例如给依赖注入的操作。”

诀窍是创建自己的作业工厂,扩展 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

【讨论】:

  • 感谢您的出色回答。 GitHub 存储库非常棒。
  • 我确实有几个关于 GitHub 代码的问题: 1. MyJobFactory 是如何在模块(MyModule)中没有提供的情况下奇迹般地注入到 MyJobScheduler 中的。 2.它不仅被注入,还接收组件(MyComponent),它也以某种方式被注入而没有任何明确的规定。这是否意味着我们可以在任何需要它的地方注入 MyComponent 来手动解决依赖关系。 3. 可以看到 MyComponent.inject 方法是用来对实例注入依赖的。这是一种标准做法,还是在这种特殊情况下更像是一种黑客行为。
  • 1.有趣的观察——是的,我认为这是在 Dagger 2 示例中没有被广泛展示或理解的东西——你不需要每个依赖项的提供者方法——如果它是第三方依赖项,你只需要一个模块(没有 @注入注释)或者如果您需要初始化模块,例如使用活动上下文...当您意识到这一点时,它会大大减少不必要的样板! :) 2. 是的,您可以注入组件本身,但这很容易被滥用。 3. 在这种情况下这是标准做法,因为作业是在外部创建的,因此这是注入其字段的唯一方法
  • 我刚刚完成了一个超级愚蠢的示例项目,以展示仅使用 @Component@Inject 的大量注入 - 根本不需要 Dagger 2 模块:github.com/glombard/so/tree/master/dagger2_modules_are_optional/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
  • 1970-01-01
相关资源
最近更新 更多