在Java Web App中使用Google Guice / Dogger在Quartz Job执行中创建对象链

问题描述

我开始在Java Web应用程序中使用Quartz创建一个cron作业,以执行清理任务之一。实际工作按预期进行,没有 Quatrz作业执行出现问题。从下面的代码片段中,当我尝试使用MyService作为工作的一部分来调用所需的方法时,依赖项无法正常工作。

MyService类的对象未创建。所以我得到一个空指针异常。为了避免这种情况,我尝试使用Google Guice(也尝试过dogger)进行管理 依赖项注入,但是MyService对象的创建依赖于其他类。

在这个示例中,让我们说CustomerService和CustomerService依赖于其他类,而这些类依赖于其他类。因此,我将最终使用Guice或Dogger创建对象创建链。

代码段:

  import com.google.inject.Inject;
    import com.google.inject.Injector;
    import com.google.inject.Singleton;
    import org.quartz.Job;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.spi.JobFactory;
    import org.quartz.spi.TriggerFiredBundle;
    
        @Singleton
        public class CustomJobFactory implements JobFactory {
        
           @Inject
           private Injector injector;
        
           @Override
           public Job newJob(TriggerFiredBundle bundle,Scheduler scheduler) throws SchedulerException {
              return (Job) injector.getInstance(bundle.getJobDetail().getJobClass());
           }
    }


public class QuartzJobHelper  {

   private final Scheduler scheduler;


   @Inject
   public QuartzSchedulerImpl(Scheduler scheduler,CustomJobFactory customJobFactory) {
      this.scheduler = scheduler;
      try {
         this.scheduler.setJobFactory(customJobFactory);
      } catch (SchedulerException e) {
         e.printStackTrace();
      }
   }

   public static void executeJob() throws Exception {

      // The Guice injector used to create instances.
      Injector injector = Guice.createInjector(new MyModule());
      JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("myjob","mygroup")
            .build();
    Trigger trigger = TriggerBuilder.newTrigger().withIdentity("mytrigger","mygroup")
            .withSchedule(CronScheduleBuilder.cronSchedule("0/1 * * * * ?")).build();

      SchedulerFactory schedulerFactory = new StdSchedulerFactory();
      Scheduler scheduler = schedulerFactory.getScheduler();

      // Inform Quartz scheduler to use our factory.
      scheduler.setJobFactory((injector.getInstance(CustomJobFactory.class));
      scheduler.scheduleJob(jobDetail,trigger);

      // Start the scheduler.
      scheduler.start();
   }

}

导入org.quartz.spi.JobFactory; 导入java.io.IOException;

public class MyModule extends AbstractModule {



   @Override
   protected void configure() {

       bind(JobFactory.class).to(MyJobFactory.class);
       bind(MyService.class).to(MyServiceImpl.class);
       bind(CustomerService.class).to(CustomerServiceImpl.class);
       bind(MyDao.class).to(MyDaoImpl.class);
       bind(CustomCache.class).to(CustomCacheImpl.class);
       bind(ProxyDao.class).to(ProxyDaoImpl.class);
       bind(RequestDao.class).to(DefaultRequestDao.class);
       |
       |
       |
       etc.. Likewise so many dependencies are there to inject but finding 100's of dependencies.
     
   }

}

public class MyJob extends org.quartz.Job {

 @Inject
 MyService service;

 public void execute(JobExecutionContext jobContext) throws JobExecutionException {
      service.cleanupJunkData();
     }    
}

class MyService {
 void cleanupJunkData();
}

@Named
class MyServiceImpl implments MyService {
   
   private CustomerService cs; 
   private MyDao dao;
   private CustomCache cache;
   
   @Inject 
   public MyServiceImpl(CustomerService cs,MyDao dao,CustomCache cache) {
     this.cs = cs;
     this.dao=dao;
     this.cache = cache;
   }
   
   @Override
   public void cleanupJunkData() {
     List<Customer> customerData = cs.getCustomerData(dao.getExpiredCustId());
     cache.clear(customerData);
   }
}

public Class MainClass {
  public static void main(Stirng[] args) {
      QuartzJobHelper.executeJob();
  }
}

有人可以建议如何处理Quartz作业中的对象创建吗?

解决方法

您没有在示例中提供任何Guice特定的代码,但是您想要创建一个JobFactory,它将负责在解雇每个作业时注入它们:

public class GuiceJobFactory implements JobFactory {
    @Inject
    private Injector guiceInjector;
    
    @Override
    public Job newJob(TriggerFiredBundle bundle,Scheduler scheduler) throws SchedulerException {
        return (Job) guiceInjector.getInstance(bundle.getJobDetail().getJobClass());
    }
}

您可以选择创建它,但是需要以某种方式将Injector放入其中。

修改

根据您的评论,我不太了解。我们有以下设置(具有多个作业):

JobThatDoesSomething:
@Inject Service1 service1;

Service1:
@Inject Dao1 dao1;
@Inject Dao2 dao2;
@Inject ValidationFactory validationFactory;

ValidationFactory:
@Inject ValidationProvider provider;

这在较高层次上是单个作业的层次结构。我们大约有100个具有相同级别的注入依赖项。据我所知,这和你完全一样吗?

你在说什么?有了这个工厂,您的:

  • 未注入MyService吗?
  • 未注入MyService.CustomerService吗?
  • 等等?

编辑2

您需要以某种方式创建注射器。我添加了您的主要代码,并举例说明了如何使用CustomModuleJobFactory

public Class MainClass {
  public static void main(Stirng[] args) {
       // You need to create your injector here
       Injector injector = Guice.createInjector(new CustomModule());

       SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
        Scheduler scheduler = schedFact.getScheduler();
        scheduler.setJobFactory(new GuiceJobFactory(injector));  // Use it here
        scheduler.start();
         
        // define the job and tie it to our HelloJob class
        JobBuilder jobBuilder = JobBuilder.newJob(MyJob.class);
        JobDataMap data = new JobDataMap();
        data.put("latch",this);
         
        JobDetail jobDetail = jobBuilder.usingJobData("example","com.QuartzSchedulerExample") 
                .usingJobData(data)
                .withIdentity("myJob","group1")
                .build();
         
         
        // Fire at curent time + 1 min every day
        Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("myTrigger","group1")
        .startAt(DateBuilder.todayAt(10,20,20))
        .withSchedule(CronScheduleBuilder.cronSchedule("0 " + (min + 1) + " " + hour + " * * ? *"))     
        .build();
         
        // Tell quartz to schedule the job using our trigger
        scheduler.scheduleJob(jobDetail,trigger);
  }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...