使用spring 结合quartz进行定时任务开发时,如果直接在job内的execute方法内使用service 或者mapper对象,执行时,出现空指针异常。
问题原因
job对象在spring容器加载时候,能够注入bean,但是调度时,job对象会重新创建,此时就是导致已经注入的对象丢失,因此报空指针异常。
解决方案
方案1:重写JobFactory类
@Component
public class JobFactory extends SpringBeanJobFactory {
@Autowired
private AutowireCapableBeanFactory beanFactory;
/**
* 这里覆盖了super的createJobInstance方法,对其创建出来的类再进行autowire。
*
* @param bundle
* @return
* @throws Exception
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
beanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
在spring配置文件内配置SchedulerFactoryBean
,使用刚才自定义的JobFactory
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" id="schedulerFactoryBean" lazy-init="true" autowire="no">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
<property name="jobFactory" ref="jobFactory"/>
</bean>
此时在job中直接注入bean即可
@Component
@DisallowConcurrentExecution
public class TestSuitJob implements Job {
@Autowired
private TestSuitService testSuitService;
方案2:静态工具类
创建工具类SpringContextJobUtil
,实现ApplicationContextAware
接口,此工具类会在spring容器启动后,自动加载,使用其提供的getBean
方法获取想要的bean即可
@Component
public class SpringContextJobUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
@SuppressWarnings("static-access" )
public void setApplicationContext(ApplicationContext contex)
throws BeansException {
// TODO Auto-generated method stub
this.context = contex;
}
public static Object getBean(String beanName){
return context.getBean(beanName);
}
public static String getMessage(String key){
return context.getMessage(key, null, Locale.getDefault());
}
}
在job内直接调用静态方法
testSuitService = (TestSuitService) SpringContextJobUtil.getBean("testSuitService");
以上两种方法均可解决无法注入问题