如何使用 Dagger 2 在 Quartz 作业中注入依赖项
How to inject dependency in a Quartz job using Dagger 2
我正在使用 Dagger 2 作为我的 DI 框架,并且我正在为其提供一个单例 class 实例。
我还使用 Quartz Scheduler 来安排作业。有没有办法将单例 class 注入到 Quartz 作业中?
匕首 2 模块:
@Module
public class MyModule {
@Provides
@Singleton
Messager provideMessager() {
return new CustomMessager();
}
}
匕首 2 组件:
@Component(modules = MyModule.class)
@Singleton
public interface MyComponent {
Messager messager();
}
Quartz 作业:
public class MyJob implements Job {
// @Inject
Messager messager;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
messager.sendMessage("Hello.");
}
}
编辑
我创建了一个调用 Quartz 作业的 MyJobScheduler
class:
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
class,我将其用作单例:
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 class 中使用 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.");
}
}
这是解决这个问题的正确方法吗?任何输入将不胜感激。
您的 EDIT 2 DependencyResolver
方法在某种程度上打败了使用 Dagger 注入依赖项的全部原因,因为您的作业从单例提供程序获取依赖项。 :-) 它完全绕过了 Dagger 的好处,所以你还不如在源依赖本身上有一个单例,比如:Messager messager = CustomMessager.getInstance()
或类似的东西。
使用依赖注入的一个原因是协助进行单元测试,在这种情况下,您将失去在单元测试中模拟 Messager 实现的能力。
在 API doc for JobFactory 中提到了在 Quartz 作业中使用依赖注入的正确方法:"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."
诀窍是创建你自己的扩展 SimpleJobFactory
的作业工厂,然后你就有机会 initialize/inject 作业的依赖项,像这样:
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
我正在使用 Dagger 2 作为我的 DI 框架,并且我正在为其提供一个单例 class 实例。
我还使用 Quartz Scheduler 来安排作业。有没有办法将单例 class 注入到 Quartz 作业中?
匕首 2 模块:
@Module
public class MyModule {
@Provides
@Singleton
Messager provideMessager() {
return new CustomMessager();
}
}
匕首 2 组件:
@Component(modules = MyModule.class)
@Singleton
public interface MyComponent {
Messager messager();
}
Quartz 作业:
public class MyJob implements Job {
// @Inject
Messager messager;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
messager.sendMessage("Hello.");
}
}
编辑
我创建了一个调用 Quartz 作业的 MyJobScheduler
class:
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
class,我将其用作单例:
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 class 中使用 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.");
}
}
这是解决这个问题的正确方法吗?任何输入将不胜感激。
您的 EDIT 2 DependencyResolver
方法在某种程度上打败了使用 Dagger 注入依赖项的全部原因,因为您的作业从单例提供程序获取依赖项。 :-) 它完全绕过了 Dagger 的好处,所以你还不如在源依赖本身上有一个单例,比如:Messager messager = CustomMessager.getInstance()
或类似的东西。
使用依赖注入的一个原因是协助进行单元测试,在这种情况下,您将失去在单元测试中模拟 Messager 实现的能力。
在 API doc for JobFactory 中提到了在 Quartz 作业中使用依赖注入的正确方法:"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."
诀窍是创建你自己的扩展 SimpleJobFactory
的作业工厂,然后你就有机会 initialize/inject 作业的依赖项,像这样:
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