关于用quartz手动创建job时,如何将job交给spring管理

一、前言

最近盘点一些老项目,在没有用一些分布式任务框架前,一般用quartz来实现定时任务,如果想让定时任务corn表达式可修改,那么必定会动态的从数据库中读取corn表达式,并动态修改。

1、通过quartz手动创建一个任务

@Slf4j
@Component
public class SchedulerMain {
   	private Scheduler scheduler;
   public void init() throws SchedulerException {
		scheduler =   StdSchedulerFactory.getDefaultScheduler();
	}
	//设置开始运行方法
	@PostConstruct
	public void start() {
	  //初始化Scheduler 
	   init();
	   //创建一个任务,指定任务类是MainJob
	   JobDetail jobDetail = new JobDetail("MainJob", "main", MainJob.class);
	   Trigger trigger = new CronTrigger(jobDetail.getFullName() + "-Trigger", "main", "0 0 0 * * ?");
 		jobDetail.getJobDataMap().put("schedulerService", schedulerService);
	    scheduler.scheduleJob(jobDetail, trigger);
	    scheduler.start();
	}
	// 关闭定时任务
	@PreDestroy
	public void shutdown() {
		try {
			if (scheduler != null) {
				scheduler.shutdown();
			}
		} catch (Exception e) {
		}
	}
}

一般手动创建一个任务就是上面过程。
看下Main的具体实现:

@Slf4j
public class MainJob implements StatefulJob {

	@Override
	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
		try {
			SchedulerService schedulerService = (SchedulerService) jobExecutionContext.getJobDetail().getJobDataMap().get("schedulerService");
			schedulerService.execute(false);
		} catch (Exception e) {
		}
	}
}

2、发现问题

看到上面我们创建的MainJob 没,这个对象没有交给spring管理,如果要往这个对象中注入对象,只能在创建这个Job的时候 通过jobDataMap放入。

SchedulerMain 对象中,这个对象是spring管理的,所以可以通过autoWrie注入属性,而job注入属性通过jobDataMap

jobDetail.getJobDataMap().put("schedulerService", schedulerService);

在使用的时候,再从jobDataMap中获取,然后调用相应的方法。这个是不是很麻烦

3、如何将我们创建的Job交给spring创建

Quartz提供了JobFactory接口,让我们可以自定义实现创建Job的逻辑。

public interface JobFactory {
    Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException;
}

这里我们用org.springframework.scheduling.quartz.SchedulerFactoryBean
注意SchedulerFactoryBean实现了FactoryBean,所以注入它时,返回是getObject方法返回的对象

@Override
public Scheduler getObject() {
    //返回scheduler,scheduler是在afterPropertiesSet方法中实例化的
	return this.scheduler;
}

@Override
public void afterPropertiesSet() throws Exception {
  try {
       this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
		//注意这一行代码,初始化AdaptableJobFactory
		this.jobFactory = new AdaptableJobFactory();	
	}
}

如果我们不指定jobFactory,那么Spring就使用AdaptableJobFactory

public class AdaptableJobFactory implements JobFactory {

	@Override
	public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
		try {
			Object jobObject = createJobInstance(bundle);
			return adaptJob(jobObject);
		}
		catch (Exception ex) {
			throw new SchedulerException("Job instantiation failed", ex);
		}
	}


	protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
	    //这里直接通过创建的对象,属性没有注入
		return bundle.getJobDetail().getJobClass().newInstance();
	}

	protected Job adaptJob(Object jobObject) throws Exception {
		if (jobObject instanceof Job) {
			return (Job) jobObject;
		}
		else if (jobObject instanceof Runnable) {
			return new DelegatingJob((Runnable) jobObject);
		}
		else {
			throw new IllegalArgumentException("Unable to execute job class [" + jobObject.getClass().getName() +
					"]: only [org.quartz.Job] and [java.lang.Runnable] supported.");
		}
	}

}

3.1、再创建一个类重写AdaptableJobFactory的newJob方法,实现Job中属性自动注入

也可直接继承SpringBeanJobFactory 这个类是AdaptableJobFactory子类,重写createJobInstance方法

@Component
public class QuartzJobFactory extends SpringBeanJobFactory {

    @Autowired
    private AutowireCapableBeanFactory beanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {

        Object jobInstance = super.createJobInstance(bundle);
        //主动注入属性
        beanFactory.autowireBean(jobInstance);

        return jobInstance;
    }
}

3.2、注入scheduler并将QuartzJobFactory 注入到Scheduler 中

  /**
 * 注入scheduler到spring,schedulerFactory这个对象返回getObject方法创建的对象
 */
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobFactory" ref="quartzJobFactory "/>
		<property name="quartzProperties">
			<props>
				<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
				<prop key="org.quartz.threadPool.threadCount">10</prop>
				<prop key="org.quartz.jobStore.misfireThreshold">6000</prop>
			</props>
		</property>
	</bean>

4、创建一个jobDetail类

@Slf4j
@Component
public class MainJob implements Job{
    //可以直接用AutoWired注入这个service
    @Autowired
    private SchedulerService  service;
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
       service.doBiz();
       //do something ....
    }
}

5、自去注入Scheduler 创建任务

@Component
public class QuartzManager {

    @Autowired
    private Scheduler schedulerFactory;
    public void saveJobToSchedule() throws SchedulerException {
        //任务体
        //创建一个任务,指定任务类是MainJob
	   JobDetail jobDetail = new JobDetail("MainJob", "main", MainJob.class);
	   Trigger trigger = new CronTrigger(jobDetail.getFullName() + "-Trigger", "main", "0 0 0 * * ?");
 	   //这里不需要再用dataMap来注入service,而直接可以在MainJob这个类中用autoWire注入想要用的service	
 	   //jobDetail.getJobDataMap().put("schedulerService", schedulerService);
 	    //加入计划
	    schedulerFactory.scheduleJob(jobDetail, trigger);
	    schedulerFactory.start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值