• 解决使用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

  • 相关阅读:
    【Python复用脚本】根据excel表格的IP和资产归属部门,保存docx文件到部门目录
    Linux-----nginx的简介,nginx搭载负载均衡以及nginx部署前后端分离项目
    3d-DNA组装基因组
    如何安装Jmeter监控服务器资源插件(JMeterPlugins + ServerAgent 方法二)?
    最新版本 Stable Diffusion 开源 AI 绘画工具之中文自动提词篇
    苍穹外卖day1--开发环境搭建
    鲜花商城系统设计与实现(Java+Web+MySQL)
    API接口名称(item_get - 获得dangdang商品详情)[item_search,item_get,item_search_shop等]
    计算机毕业设计springboot+vue基本微信小程序的校园二手闲置物品交易小程序 uniapp
    阿里首推的“SpringBoot+Vue全栈项目”有多牛X?
  • 原文地址:https://blog.csdn.net/Supreme7/article/details/125538369