Quartz 随笔 JobStore接口

  • org.quartz.spi.JobStore 是任务存储的顶层接口类
  • org.quartz.simpl.RAMJobStore 是内存存储机制实现类
  • org.quartz.impl.jdbcjobstore.JobStoreSupport 是基于JDBC数据库存储的抽象类
  • org.quartz.impl.jdbcjobstore.JobStoreCMT 是受应用容器管理事物的数据库存储实现类
  • org.quartz.impl.jdbcjobstore.JobStoreTX 是不受应用容器事物管理的数据库存储实现类
org.quartz.jobStore.class = 上面提到的具体实现类

在quzrtz.properties 中配置以上代码来告诉quartz我们使用何种存储机制

存储机制对比

内存存储机制
org.quartz.simpl.RAMJobStore
使用内存存储的优点是任务的存储和读取的速度极快,和数据库持久化相比差别还是非常大的,而且框架搭建简单,开箱即用。它的缺点是当Quartz程序或应用程序停止了,伴随在内存中的数据也会被回收,任务等数据就永久丢失了。
数据库存储机制
org.quartz.impl.jdbcjobstore.JobStoreTX
TX就是事物的意思,此存储机制用于Quartz独立于应用容器的事物管理,如果是Tomcat容器管理的数据源,那我们定义的事物也不会传播给Quartz框架内部。通俗的讲就是不管我们的Service服务本身业务代码是否执行成功,只要代码中调用了Quartz API的数据库操作,那任务状态就永久持久化了,就算业务代码抛出运行时异常任务状态也不会回滚到之前的状态。

org.quartz.impl.jdbcjobstore.JobStoreCMT
CMT的全称是Container Managed Transactions,表示容器管理事物,也就是让应用容器托管事物。这里假设应用容器是Tomcat,并且项目和Quartz都是使用Tomcat配置的数据源,那么项目和Quartz的代码中就可以共用同一个事物,不管是业务代码还是Quartz内部抛出异常,Service服务内的所有数据操作都会回滚到原始状态。JobStoreCMT和JobStoreTX最大的区别是JobStoreCMT需要配置两个数据源,一个是受应用容器管理的数据源,还有一个是不受应用容器管理的数据源。
这里需要想一想为什么需要两个数据源?
我个人的理解是不受应用容器管理的数据源用来由Quartz内部进行"增删改查",假如一个触发器已失效,那么Quartz框架内部就会自动删除这个触发器并提交事物,而无需开发人员的项目代码来处理,全由Quartz内部管理。

选用哪种存储方式

        什么情况下使用RAMJobStore内存存储方式呢?

  根据开发中的使用经验,发现有些任务是随着项目启动而启动的,就算项目关闭或系统宕机,那也没关系,因为项目重新启动后此任务又会随之启动。如果项目中只存在这类任务,那么就可以用内存存储。随着项目启动有几种常用的实现方式,第一种是通过实现ServletContextListener监听器接口,然后在接口实现类的contextInitialized()方法中编写启动Job的硬编码;第二种是通过Quartz的XML配置文件启动任务。

        什么情况下使用JobStoreTX数据库存储方式呢?

 使用这种方式需要注意的是,如果在一个业务代码中需要创建一个Job,那么请把创建Job的代码编写在服务代码的最后面,确保业务代码运行成功并且没有抛异常再去启动Job,如果启动Job失败的时候请抛出一个运行时异常使业务代码进行回滚。
例子:

@Transactional
public void demoService(TaskStore taskStore) {
    // 先执行插入业务操作
    taskStoreService.insert(taskStore);
    // 再执行更新业务操作
    taskDetailService.update(taskDetail);
    // 最后启动定时任务
    QuartzUtils.addJob("testName", DemoJob.class, "0 * * * * * ?");
}

注意例子中的addJob()方法中捕获了异常后进行重新封装再抛出运行时异常的,目的是Quartz内部错误时确保业务代码回滚。

        什么情况下使用JobStoreCMT数据库存储方式呢?

  JobStoreCMT和JobStoreTX的区别前文已经介绍了,在实际开发的过程中我还没有在项目中使用过此种方式。一般情况下都是使用的JobStoreTX。如果大家的项目中有着严格的事物管理,那么建议使用JobStoreCMT存储方式。

 

@Component
public  class JobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory  capableBeanFactory;
    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        // 调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        // 进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

这个类的作用就是讲Job的实例化交给IOC去进行。
其实问题在于:
Job对象的实例化过程是在Quartz中进行的,注入的实体类是在Spring容器当中的 所以在job中无法注入Srping容器的实体类。
解决方案:将Job Bean也纳入到Spring容器的管理之中,Spring容器自然能够为Job Bean自动装配好所需的依赖。
如何纳入:Job的创建都是通过JobFactory创建的。

官网解释为证:
翻译:JobFactory负责生成Job类的实例。
JobFactory 有2个实现类:AdaptableJobFactory 和 SimpleJobFactory。
自定义的工厂类 JobFactory 继承 AdaptableJobFactory 。
通过调用父类 AdaptableJobFactory 的方法createJobInstance来实现对Job的实例化。
在Job实例化完以后,再调用自身方法为创建好的Job实例进行属性自动装配并将其纳入到Spring容器的管理之中。(通过AutowireCapableBeanFactory纳入)。

 

 

转载于:https://my.oschina.net/mclimber/blog/3079801

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值