简体   繁体   English

如何使用Dagger 2在Quartz作业中注入依赖项

[英]How to inject dependency in a Quartz job using Dagger 2

I am using Dagger 2 as my DI framework and I am providing a singleton class instance with it. 我使用Dagger 2作为我的DI框架,并为其提供了一个singleton类实例。

I also use Quartz Scheduler to schedule jobs. 我还使用Quartz Scheduler来调度作业。 Is there any way to inject the singleton class into the Quartz job? 有什么方法可以将单例类注入Quartz作业吗?

Dagger 2 module: Dagger 2模块:

@Module
public class MyModule {

    @Provides
    @Singleton
            Messager provideMessager() {

        return new CustomMessager();
    }
}

Dagger 2 component: 匕首2组件:

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

    Messager messager();
}

Quartz Job: 石英作业:

public class MyJob implements Job {

    // @Inject
    Messager messager;

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

        messager.sendMessage("Hello.");
    }

}

EDIT 编辑

I have created a MyJobScheduler class that calls the Quartz Job: 我创建了一个MyJobScheduler类,该类调用Quartz Job:

    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 编辑2

So I managed to configure it to work, but I don't know if this is the correct approach. 因此,我设法对其进行了配置,但我不知道这是否是正确的方法。

First I created a DependencyResolver class, which I use as a singleton: 首先,我创建了一个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();
    }
}

Then I called the initialize method in the main method: 然后我在main方法中调用了initialize方法:

DependencyResolver.initialize();

MyComponent myComponent = DependencyResolver.getMyComponent();

And I used the DependencyResolver in MyJob class to get the Messager singleton instance. 我在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.");
    }
}

Is this the correct way to solve this issue? 这是解决此问题的正确方法吗? Any input will be greatly appreciated. 任何输入将不胜感激。

Your EDIT 2 DependencyResolver approach kind of defeats the whole reason to use Dagger to inject the dependencies, because your job gets the dependency from a singleton provider. 您的EDIT 2 DependencyResolver方法克服了使用Dagger注入依赖项的全部原因,因为您的工作从单例提供程序获取了依赖项。 :-) It completely bypasses the benefit of Dagger, so you might as well just have a singleton on the source dependency itself, like: Messager messager = CustomMessager.getInstance() or something like that. :-)它完全绕过了Dagger的好处,因此您可能还对源依赖项本身只有一个单例,例如: Messager messager = CustomMessager.getInstance()或类似的东西。

One reason to use Dependency Injection, is to assist with unit testing, and in this case you're losing the ability to mock your Messager implementation in a unit test. 使用依赖注入的原因之一是协助进行单元测试,在这种情况下,您将失去在单元测试中模拟Messager实现的功能。

The proper way to use dependency injection with Quartz jobs is mentioned in the API doc for JobFactory : "This interface may be of use to those wishing to have their application produce Job instances via some special mechanism, such as to give the opertunity for dependency injection ." JobFactoryAPI文档中提到了将依赖注入与Quartz作业一起使用的正确方法: “该接口可能对那些希望其应用程序通过某些特殊机制生成Job实例的人有用,例如为依赖注入提供操作性“。

The trick is to create your own job factory that extends SimpleJobFactory and then you have an opportunity to initialize/inject the job's dependencies, something like this: 诀窍是创建自己的扩展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;
    }
}

And then you tell the scheduler to use your job factory: 然后,您告诉调度程序使用作业工厂:

scheduler.setJobFactory(myJobFactory);

See the full code here on GitHub 在GitHub上查看完整代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM