如题,在Spring中集成Quartz框架创建基于JobDetailFactoryBean的定时任务时,如果在任务中注入Spring管理的Bean将会爆空指针异常。比如:
Java
package cn.zifangsky.job;
import java.text.Format;
import java.text.SimpleDateFormat;
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;
import cn.zifangsky.manager.TestManager;
public class TestJob extends QuartzJobBean {
@Autowired
private TestManager testManager;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Date current = new Date();
Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
testManager.test();
System.out.println("job1--------" + format.format(current) + "---------");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29packagecn.zifangsky.job;
importjava.text.Format;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importorg.quartz.JobExecutionContext;
importorg.quartz.JobExecutionException;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.scheduling.quartz.QuartzJobBean;
importcn.zifangsky.manager.TestManager;
publicclassTestJobextendsQuartzJobBean{
@Autowired
privateTestManagertestManager;
@Override
protectedvoidexecuteInternal(JobExecutionContextjobExecutionContext)throwsJobExecutionException{
Datecurrent=newDate();
Formatformat=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
testManager.test();
System.out.println("job1--------"+format.format(current)+"---------");
}
}
然后启动后爆以下错误:
严重: Job (DEFAULT.jobDetail threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.NullPointerException]
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: java.lang.NullPointerException
at cn.zifangsky.job.TestJob.executeInternal(TestJob.java:23)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
... 1 more
1
2
3
4
5
6
7
8
9严重:Job(DEFAULT.jobDetailthrewanexception.
org.quartz.SchedulerException:Jobthrewanunhandledexception.[Seenestedexception:java.lang.NullPointerException]
atorg.quartz.core.JobRunShell.run(JobRunShell.java:213)
atorg.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Causedby:java.lang.NullPointerException
atcn.zifangsky.job.TestJob.executeInternal(TestJob.java:23)
atorg.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
atorg.quartz.core.JobRunShell.run(JobRunShell.java:202)
...1more
其实,出现这个问题的原因在于:通过继承QuartzJobBean这个类的方式来创建定时任务,这个类在实例化时是被Quartz实例化的,同时没有注入到Spring中。因此就导致了被Spring所管理的Bean不能被自动注入进来
解决方案:
其实解决方案很简单,就是自定义一个JobFactory,在Quartz生成任务的实例后,手动将这个实例注入成一个Spring的Bean即可
(1)自定义一个JobFactory:
Java
package cn.zifangsky.job;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Component("autowiringBeanJobFactory")
public class AutowiringBeanJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory autowiringBeanJobFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//创建jobInstance
Object jobInstance = super.createJobInstance(bundle);
//向Spring中注入这个bean
autowiringBeanJobFactory.autowireBean(jobInstance);
return jobInstance;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25packagecn.zifangsky.job;
importorg.quartz.spi.TriggerFiredBundle;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.config.AutowireCapableBeanFactory;
importorg.springframework.scheduling.quartz.AdaptableJobFactory;
importorg.springframework.stereotype.Component;
@Component("autowiringBeanJobFactory")
publicclassAutowiringBeanJobFactoryextendsAdaptableJobFactory{
@Autowired
privateAutowireCapableBeanFactoryautowiringBeanJobFactory;
@Override
protectedObjectcreateJobInstance(TriggerFiredBundlebundle)throwsException{
//创建jobInstance
ObjectjobInstance=super.createJobInstance(bundle);
//向Spring中注入这个bean
autowiringBeanJobFactory.autowireBean(jobInstance);
returnjobInstance;
}
}
(2)修改quartz的配置文件:
i)添加自动扫描上面那个JobFactory所在的包:
XHTML
1
ii)修改配置使用我们自定义的jobFactory:
XHTML
1
2
3
4
5
6
7
8
9
(3)测试:
再次启动运行,可以发现就没有爆空指针异常了,输出如下:
测试调用Spring注解的具体业务类
job1--------2016-10-08 15:13:35---------
测试调用Spring注解的具体业务类
job1--------2016-10-08 15:13:37---------
...
1
2
3
4
5
6测试调用Spring注解的具体业务类
job1--------2016-10-0815:13:35---------
测试调用Spring注解的具体业务类
job1--------2016-10-0815:13:37---------
...