• 解决使用Quartz执行的任务对象(job)中无法注入bean的问题


    问题描述

    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());
        }
    }
    
    • 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

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试类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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    reference

    其他方案

    其他方法都是重写JobFactory实现的,步骤较多,较为繁琐,日后再研究。
    主要思路如下:
    如果在Job中注入Spring管理的Bean,需要先把Quartz的Job也让Spring管理起来,因此,我们需要重写JobFactory

    参考:https://www.w3cschool.cn/quartz_doc/quartz_doc-1xbu2clr.html

  • 相关阅读:
    WMS之添加View
    计算机二级(Python)真题讲解每日一题:《字典字符查找》
    nacos配置启动
    基于写时复制技术的并发集合———CopyOnWriteArrayList源码分析
    AAA认证,授权,计费
    2022/08/19、20 day06/07:Linux的redis安装
    分享一下怎么做一个房间预定链接
    Dynamic-TP入门初探
    uniapp中unicloud接入支付宝订阅消息完整教程
    GC垃圾收集器和收集算法及JVM调优
  • 原文地址:https://blog.csdn.net/Supreme7/article/details/125538369