Spring&Quartz集成自定义注释

我们知道Spring支持与Quartz框架集成。 但是到目前为止,Spring仅支持静态XML声明方法。

如果想了解如何将Spring与Quartz集成,可以参考Spring + Quartz + JavaMail集成教程

作为宠物项目要求的一部分,我必须动态安排工作,并且想到了以下两个选项:

1.使用注释提供作业元数据
2.从数据库加载作业元数据

现在,我想到了继续使用基于注释的方法,并且也希望将其与Spring集成。 这是我的方法。

1.创建一个自定义注解QuartzJob

package com.sivalabs.springsamples.jobscheduler;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@Scope("prototype")
public @interface QuartzJob 
{
 
 String name();
 String group() default "DEFAULT_GROUP";
 String cronExp();
}

2.创建一个ApplicationListener来扫描所有Job实施类,并使用Quartz Scheduler调度它们。

package com.sivalabs.springsamples.jobscheduler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.JobDetailBean;

public class QuartJobSchedulingListener 
    implements ApplicationListener<ContextRefreshedEvent>
{ 
 @Autowired
 private Scheduler scheduler;
 
 @Override
 public void onApplicationEvent(ContextRefreshedEvent event)
 {
  try 
  {
    ApplicationContext applicationContext = event.getApplicationContext();
    List<CronTriggerBean> cronTriggerBeans = this.loadCronTriggerBeans(applicationContext);
    this.scheduleJobs(cronTriggerBeans);
  } 
  catch (Exception e) 
  {
    e.printStackTrace();
  }
 }
 
 private List<CronTriggerBean> loadCronTriggerBeans(ApplicationContext applicationContext)
 {
   Map<String, Object> quartzJobBeans = 
    applicationContext.getBeansWithAnnotation(QuartzJob.class);
  
   Set<String> beanNames = quartzJobBeans.keySet();
  
   List<CronTriggerBean> cronTriggerBeans = new ArrayList<CronTriggerBean>();
  
   for (String beanName : beanNames) 
   {
     CronTriggerBean cronTriggerBean = null;
     Object object = quartzJobBeans.get(beanName);
     System.out.println(object);
     try 
     {
      cronTriggerBean = this.buildCronTriggerBean(object);
     } 
     catch (Exception e) 
     {
      e.printStackTrace();
     }
   
     if(cronTriggerBean != null)
     {
      cronTriggerBeans.add(cronTriggerBean);
     }
   }
   return cronTriggerBeans;
 }
 
 public CronTriggerBean buildCronTriggerBean(Object job) throws Exception
 {
   CronTriggerBean cronTriggerBean = null;
   QuartzJob quartzJobAnnotation = 
     AnnotationUtils.findAnnotation(job.getClass(), QuartzJob.class);
     
   if(Job.class.isAssignableFrom(job.getClass()))
   {
     System.out.println("It is a Quartz Job");
     cronTriggerBean = new CronTriggerBean();
     cronTriggerBean.setCronExpression(quartzJobAnnotation.cronExp());    
     cronTriggerBean.setName(quartzJobAnnotation.name()+"_trigger");
     //cronTriggerBean.setGroup(quartzJobAnnotation.group());
     JobDetailBean jobDetail = new JobDetailBean();
     jobDetail.setName(quartzJobAnnotation.name());
     //jobDetail.setGroup(quartzJobAnnotation.group());
     jobDetail.setJobClass(job.getClass());
     cronTriggerBean.setJobDetail(jobDetail);   
   }
   else
   {
    throw new RuntimeException(job.getClass()+" doesn't implemented "+Job.class);
   }
   return cronTriggerBean;
 }
 
 protected void scheduleJobs(List<CronTriggerBean> cronTriggerBeans)
 {
  for (CronTriggerBean cronTriggerBean : cronTriggerBeans) 
  {
    JobDetail jobDetail = cronTriggerBean.getJobDetail();
    try 
    {
     scheduler.scheduleJob(jobDetail, cronTriggerBean);
    } 
    catch (SchedulerException e) 
    {
     e.printStackTrace();
    }   
  }
 }
}

3.创建一个自定义的JobFactory,以将Spring bean用作Job实现对象。

package com.sivalabs.springsamples.jobscheduler;

import org.quartz.Job;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public class SpringQuartzJobFactory extends SpringBeanJobFactory
{
 @Autowired
 private ApplicationContext ctx;

 @Override
 protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception 
 {
     @SuppressWarnings("unchecked")
  Job job = ctx.getBean(bundle.getJobDetail().getJobClass());
     BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);
     MutablePropertyValues pvs = new MutablePropertyValues();
     pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap());
     pvs.addPropertyValues(bundle.getTrigger().getJobDataMap());
     bw.setPropertyValues(pvs, true);
     return job;
 } 
}

4.创建Job实施类,并使用@QuartzJob对其进行批注

package com.sivalabs.springsamples.jobscheduler;

import java.util.Date;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

@QuartzJob(name="HelloJob", cronExp="0/5 * * * * ?")
public class HelloJob extends QuartzJobBean
{  
 @Override
 protected void executeInternal(JobExecutionContext context)
   throws JobExecutionException
 {
  System.out.println("Hello Job is running @ "+new Date());
  System.out.println(this.hashCode());  
 }
}

5.在applicationContext.xml中配置SchedulerFactoryBean和QuartJobSchedulingListener

<beans>
 <context:annotation-config></context:annotation-config>
 <context:component-scan base-package="com.sivalabs"></context:component-scan>
 
 <bean class="com.sivalabs.springsamples.jobscheduler.QuartJobSchedulingListener"></bean>
 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <property name="jobFactory">
   <bean class="com.sivalabs.springsamples.jobscheduler.SpringQuartzJobFactory"></bean>
  </property>
 </bean>
 
</beans>

6.使用测试客户端启动上下文

package com.sivalabs.springsamples;

import org.quartz.Job;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sivalabs.springsamples.jobscheduler.HowAreYouJob;
import com.sivalabs.springsamples.jobscheduler.InvalidJob;

public class TestClient
{
 public static void main(String[] args)
 {
  ApplicationContext context = 
  new ClassPathXmlApplicationContext("applicationContext.xml");
  System.out.println(context);  
 }

}

参考: JCG合作伙伴 Siva在“我的技术实验”博客上的 使用自定义批注进行Spring和Quartz集成

相关文章 :

翻译自: https://www.javacodegeeks.com/2011/10/spring-quartz-integration-with-custom.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值