Spring中使用Quartz调度线程

最近项目中采用spring的quartz调度自动发送邮件业务,应用JobDetailBean实现,在应用过程中发现并发情况下对事务控制做得不够好,看如下代码:
<!-- 定时自动发送邮件的配置 -->
<!-- JobDetailBean方式,任务是无状态的,导致多个线程并发执行,产生业务重复操作,改用下面MethodInvokingJobDetailFactoryBean方式实现 -->
<!--
<bean id="autoSendEmailJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>cn.xxx.videotrackerlive.service.takedown.quartztimer.AutoTakedownEmailCronTrigger</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="accountService">
<ref bean="accountService" />
</entry>
<entry key="userService">
<ref bean="userService" />
</entry>
<entry key="takedownNoticeService">
<ref bean="takedownNoticeService" />
</entry>
<entry key="autoTakedownSettingService">
<ref bean="autoTakedownSettingService" />
</entry>
<entry key="mailListService">
<ref bean="mailListService" />
</entry>
<entry key="emailTemplateService">
<ref bean="emailTemplateService" />
</entry>
<entry key="matchService">
<ref bean="matchService" />
</entry>
</map>
</property>
</bean>
-->


google资料发现spring还有一种方式是MethodInvokingJobDetailFactoryBean,通过这个factroyBean包装Quartz任务,这样就不必继承job类去实现了,看如下:

<!--MethodInvokingJobDetailFactoryBean方式,指定concurrent设为false,多个job不会并发运行,默认concurrent为true-->
<bean id="autoSendEmailJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="autoSendEmailAction"/>
<property name="targetMethod" value="autoSendEmail"/>
<property name="concurrent" value="false"/>
</bean>
<bean id="autoSendEmailCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="autoSendEmailJobDetail"/>
<property name="cronExpression">
<value>${cronExpression}</value>
</property>
</bean>
<bean id="autoSendEmailSchedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="autoSendEmailCronTrigger"/>
</list>
</property>
</bean>
<!-- end 定时自动发送邮件的配置 -->

action配置
<bean id="autoSendEmailAction" class="cn.xxx.videotrackerlive.web.struts.takedown.AutoSendEmailAction" init-method="clearSession" >
<property name="accountService" ref="accountService" />
<property name="userService" ref="userService" />
<property name="takedownNoticeService" ref="takedownNoticeService" />
<property name="autoTakedownSettingService" ref="autoTakedownSettingService" />
<property name="mailListService" ref="mailListService" />
<property name="emailTemplateService" ref="emailTemplateService" />
<property name="matchService" ref="matchService" />
</bean>



参考资料:
Spring 为创建Quartz 的 Scheduler,Trigger 和 JobDetail提供了便利的FactoryBean类,以便能够在Spring容器中享受注入的好处。此外Spring还提供了一些便利工具类直接将Spring中的Bean包装成合法的任务。概括来说他提供了两方面的支持:
1. 为Quartz的重要组建类提供更具Bean风格的扩展类;
2. 提供创建Scheduler的BeanFactory类,方便在Spring环境下创建对应的组件对象,并结合Spring容器生命周期进行启动和停止的动作。
让我们来具体研究研究Spring对Quartz的支持,相当好用哦。
创建JobDetail
用户可以直接使用Quartz的JobDetail在Spring中配置一个JobDetail Bean,但是JobDetail使用带参的构造函数,对于习惯通过属性配制的Spring用户来说存在使用上的不便。为此Spring通过扩展JobDetail提供了一个更具Bean风格的JobDetailBean。

JobDetailBean扩展于Quartz的JobDetail。使用该Bean声明JobDetail时,Bean的名字即是任务的名字,如果没有指定所属组,就使用默认组。除了JobDetail中的属性外,还定义了以下属性:

JobClass:类型为Class,实现Job接口的任务。

BeanName:默认为Bean的ID名,通过该属性显式指定Bean名称,它对应任务的名称。

JobDateAsMap:类型为Map,为任务所对应的JobDataMap提供值。之所以需要提供这个属性,是因为用户无法在Spring配置文件为JobDataAsMap类型的属性提供信息,所以Spring通过jobDataAsMap设置JobDataMap的值。

ApplicationContextJobDataKey:用户可以将Spring ApplicationContext的引用保存到JobDataMap中,以便在Job的代码中访问ApplicationContext。为了达到这个目的,用户需要指定一个键,用以在jobDataAsMap中保存 ApplicationContext,如果不设置此键,JobDetailBean就不将ApplicationContext放入到JobDataMap中。
JobListenerNames;类型为String[],指定注册在Scheduler中的JobListeners名称,以便让这些监听器对本任务的事件进行监听。


下面配置片断使用JobDetailBean在Spring中配置一个JobDetail:

<bean name=”jobDetail” class=”org.springframework.schedling.quartz.jobDetaliBean”>

<property name=”jobClass”value=”com.test.Myjob”/>

<property name=”jobDataAsMap”>

<map>

<entry key=”size” value=”10”/>

</map>

</property>

<property name=”applicationContextJobDataKey”value=”applicationContext”/>

</bean>








JobDetailBean封装了MyJob任务类,并为Job对应JobDataMap设置了一个size的数据。此外,通过指定 applicationContextDataKey让Job的JobDataMap持有Spring ApplicationContext的引用。
同样的,Spring提供了一个MethodInvokingJobDetailFactoryBean,通过这个FactoryBean可以将Spring容器中Bean的方法包装成Quartz任务,这样开发者就不必为Job创建对应的类。而且定义起来想当方便

通常情况下,任务都定义在一个业务类方法中。这时,为了满足Quartz Job接口的规定,还需要定义一个引用业务类方法的实现类。为了避免创建这个只包含一行调用代码的Job实现类,Spring为我们提供了MethodInvokingJobDetailFactoryBean,借由该FactoryBean,我们可以将一个Bean的某种方法封装成满足Quartz 要求的Job。来看一个具体的例子:



<bean id="jobDetail_1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

<property name="targetObject" ref="myService">

<property name="targetMethod" value="doJob">

<property name="concurrent" value="false">

</bean>

<bean id="myService" class="com.test.myService" />





jobDetail_1将MyService#doJob()封装成一个任务,同时通过concurrent属性指定任务的类型,默认情况下封装为无状态的任务,如果希望目标封装为有状态的任务,仅需要将concurreng设置成false就可以了。

Spring通过名为concurrent的属性指定任务的类型,能够更直接地描述任务执行的方式(有状态的任务不能并发执行,无状态的任务可并发执行)

public class MyService(){
public void doJob(){
System.out.println("doJobing.....");
}
}


doJob()方法即可以是static,也可以是非static的,但不能拥有方法入参。通过MethodInvokingJobDetailFactoryBean产生的JobDetail不能被序列化,所以不能不持久化到数据库中,如果希望使用持久化任务,用户只能创建正规的Quartz的Job实现了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值