java job 配置_spring+quartz两种整合方式:代码创建job+xml配置创建job

quartz交流QQ群:77383408,喜欢的同行一起来探讨问题吧

最近在项目中需要用到quartz,开始使用的xml配置创建的job,一切ok。后来觉得每次添加任务都要写一大段xml,就将job放入了数据库,在spring启动时去启动数据库中保存的所有job。

其中遇到问题,无法注入spring管理的bean。本文是解决方案,研究了几天,终于找到原因了!

首先,本文实现使用的是内存型,没有持久化到数据库。

一、quartz.properties文件

#调度器名,无关紧要,名字任意定

org.quartz.scheduler.instanceName = XXScheduler

org.quartz.scheduler.instanceId = AUTO

#============================================================================

# Configure ThreadPool   配置数据库连接池

#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool

org.quartz.threadPool.threadCount = 12

org.quartz.threadPool.threadPriority = 5

#============================================================================

# Configure JobStore  配置做业存储方式

#============================================================================

#相当于扫描频率,如果系统基于秒级,应培植成1000,quartz默认为分级(60000)

org.quartz.jobStore.misfireThreshold = 1000

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

二、创建任务Job

方法一:使用xml方式配置job

0/1 * * * * ?

好了,至此使用xml方式配置job就全部完毕了。

其中值得注意的是下面两句代码:自定义MyJobFactory,在job类里面才可以注入spring的service。

public class MyJobFactory extends AdaptableJobFactory {

// 这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.

@Autowired

private AutowireCapableBeanFactory capableBeanFactory;

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {

// 调用父类的方法

Object jobInstance = super.createJobInstance(bundle);

// 进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.

capableBeanFactory.autowireBean(jobInstance);

return jobInstance;

}

}

/**

* Job任务类,实现Job接口,可以成功注入service

*/

public class JobClassTest implements Job {

@Autowired

private ProductBaseDao productBaseDao;

@Override

public void execute(JobExecutionContext context) throws JobExecutionException {

ProductBase p = productBaseDao.load(ProductBase.class, 2);

System.out.println("注入service成功!查询结果为:"+p);

}

}

至此,启动容器,job成功启动。

方式二:使用代码创建Job

表结构:本示例只需要一张表即可!

f3f3fc043d51d65452cf1e9ee4023499.png

数据库有了记录,那么我们就需要在spring容器启动后,将所有记录获取出来,并通过代码创建每一个job。

在applicationContext.xml配置文件最末加上这一句,即可在spring启动后,去执行指定类中的方法。

/**

* 在Spring容器将所有的Bean都初始化完成之后的操作

*/

public class InstantiationTracingBeanPostProcessor implements ApplicationListener {

@Autowired

private TimerJobService timerJobService;

@Autowired

private MyJobFactory myJobFactory;

@Override

public void onApplicationEvent(ContextRefreshedEvent event) {

// 避免onApplicationEvent方法被执行两次

if(event.getApplicationContext().getParent() == null){

try {

// 获取Scheduler对象,并自定义jobFactory

Scheduler scheduler = QuartzUtil.getInstance();

scheduler.setJobFactory(myJobFactory);

// 查询所有正常状态的定时任务,并在容器启动后,启动任务

List jobs = timerJobService.getNormalList();

for(TimerJob record : jobs){

Integer id = record.getId();

String name = record.getJobName()+"_"+id;

String group = record.getJobGroup()+"_"+id;

// 加载job类

Class extends Job> clazz = null;

try {

clazz = (Class extends Job>) Class.forName(record.getClassName());

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

//生成jobDetail

JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(name, group).build();

//表达式调度构建器

CronScheduleBuilder cornSB= CronScheduleBuilder.cronSchedule(record.getCronExpression());

//生成触发器

CronTrigger trigger = (CronTrigger)TriggerBuilder.newTrigger().withIdentity(name, group).withSchedule(cornSB).build();

//添加job

scheduler.scheduleJob(jobDetail, trigger);

}

//开始执行shceduler

scheduler.start();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

其中创建Scheduler实例方法为:

public class QuartzUtil {

private static SchedulerFactory ssf = new StdSchedulerFactory();

/**

* 获取Scheduler实例,使用工厂模式获取

* @return

*/

public static Scheduler getInstance(){

Scheduler sched = null;

try {

sched = ssf.getScheduler();

} catch (SchedulerException e) {

e.printStackTrace();

}

return sched;

}

}

其中关键代码为:scheduler.setJobFactory(myJobFactory) ;同xml配置一样,需要指定自定义的JobFactory。

最开始,我是这样设置的:scheduler.setJobFactory(new MyJobFactory());

可是这样的结果就是,任务全部启动了,可是在job任务类注入不了bean。思考了很久,才突然发现, MyJobFactory是使用new关键字实例化出来的,在spring中,自己new出来的都不会交给spring的context去管理!!!

既然找到问题所在,解决就简单多了,只需要将MyJobFactory交给spring中去,再在上文通过注解注入即可!

在MyJobFactory.java类最上面添加@component注解,启动时spring去扫描组件会将该类注入。

@Component

public class MyJobFactory extends AdaptableJobFactory {......}

至此,问题全部解决,两种创建job的方法,个人觉得第二种比较简单。需要新增任务时,只需要在数据库添加一条记录,再添加一个对应的job类即可。

有了这一张表,同样可以配置后台页面,实现对任务的控制,这里就不讲啦!

最后,欢迎喜欢quartz的人,加入QQ群:77383408

把你的问题说出来集思广益,避免大家重蹈覆辙。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值