springBoot整合Quartz后,job中注入的业务service,使用@Autowired获取的对象为null,报空指针异常。
使用spring 结合quartz进行定时任务开发时,如果直接在job内的execute方法内使用service 或者mapper对象,执行时,出现空指针异常。
Spring容器可以管理Bean,但是Quartz的job是自己管理的,job是无法被容器识别到的,即使在自定义的job上加上@Component注解,依然无效。那是因为,job对象在spring容器加载时候,能够注入bean,但是调度时,job对象会重新创建,此时就是导致已经注入的对象丢失,因此报空指针异常。
网上的解决方法有许多,尝试了许多,最终选择了自定义静态工具类的方式。
创建工具类SpringContextJobUtil,实现ApplicationContextAware接口,此工具类会在spring容器启动后,自动加载,使用其提供的getBean方法获取想要的bean即可。
SpringContextJobUtil
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.Locale;
@Component
public class SpringContextJobUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext contex)
throws BeansException {
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());
}
}
Myjob
import com.example.phenocam.entity.Picture;
import com.example.phenocam.repository.PicRepository;
import org.quartz.*;
import java.util.List;
public class Myjob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
PicRepository picRepository = (PicRepository) SpringContextJobUtil.getBean("picRepository");//从容器中拿
List<Picture> all = picRepository.findAll();
System.out.println(all);
}
}
测试类MyController
@Controller
public class MyController {
@ResponseBody
@RequestMapping("/ttt")
public void s() throws SchedulerException {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
Trigger trigger = TriggerBuilder.newTrigger()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever())
.build();
JobDetail job =JobBuilder.newJob(Myjob.class).build();
scheduler.scheduleJob(job,trigger);
scheduler.start();
}
}
其他方法都是重写JobFactory实现的,步骤较多,较为繁琐,日后再研究。
主要思路如下:
如果在Job中注入Spring管理的Bean,需要先把Quartz的Job也让Spring管理起来,因此,我们需要重写JobFactory
参考:https://www.w3cschool.cn/quartz_doc/quartz_doc-1xbu2clr.html