springboot + quartz注入Bean方式动态添加任务

678 阅读2分钟

前言

在做定时任务时,往往都会在Job的业务逻辑中依赖其他业务的来完成整个任务。

在使用Quartz时,Job的创建是new出来的,所以在Job使用@Autowired自动装配注解是无效的。

为了在job中,能实现自动装配的功能,则需要通过自定义Job的工厂来实现这个需求。

开始

第一步:自定义Job工厂类

    /**
     * 自定义Job工厂类
     * <p>
     * job的初始化时quartz在执行时new出来的。不受spring的管理,无法注入相关的依赖bean
     * 所以需要在job在被创建的时候,使用AutowireCapableBeanFactory实现自动转配Job实例
     * <p>
     * AutowireCapableBeanFactory,可以利用这个接口自动装配那些不在spring控制范围内的bean实例
     */
    @Component
    public class AutowireJobFactory extends AdaptableJobFactory {

        @Autowired
        private AutowireCapableBeanFactory capableBeanFactory;

        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Object jobInstance = super.createJobInstance(bundle);
            //自动装配实例
            capableBeanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }

第二步:配置

    @Configuration
    public class QuartzConfig {
        //自定义Job工厂类
        @Autowired
        private ConvertJobFactory convertJobFactory;

        @Bean
        public SchedulerFactoryBean schedulerFactory() {
            SchedulerFactoryBean bean = new SchedulerFactoryBean();
            bean.setJobFactory(convertJobFactory);
            return bean;
        }
    }

第三步:Quartz任务添加工具类

    @Component
    public class QuartzManager {
        @Autowired
        private SchedulerFactoryBean schedulerFactory;

        public void addJob(Class<? extends Job> jobClass, String jobName, String groupName, String cron) {
            try {
                //创建jobDetail实例,绑定Job实现类
                //指明job的名称,所在组的名称,以及绑定job类
                JobDetail jobDetail = JobBuilder.newJob(jobClass)
                        .withIdentity(jobName, groupName) //任务名称和组构成任务key
                        .build();
                //定义调度触发规则
                //使用cornTrigger规则
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(jobName, groupName)//触发器key
                        .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                        .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                        .startNow().build();

                Scheduler scheduler = schedulerFactory.getScheduler();
                //把作业和触发器注册到任务调度中
                scheduler.scheduleJob(jobDetail, trigger);
                // 启动
                if (!scheduler.isShutdown()) {
                    scheduler.start();
                }
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    }

第四步:编写Job

    @Component
    public class Cad2ImgConvertQuartz implements Job, InitializingBean {
        @Autowired
        private QuartzManager quartzManager;

        /**
         * Job类需要实现的方法,具体在这个方案里面实现任务的业务逻辑
         */
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            //TODO 业务逻辑
        }

        /**
         * InitializingBean类需要实现的方法,作用是在服务初始化后执行。
         * 这里服务初始化后,直接把Job添加到任务调度器里
         */
        @Override
        public void afterPropertiesSet() throws Exception {
			//添加当前任务
			quartzManager.addJob(this.getClass(),
			this.getClass().getSimpleName(),
			QuartzConfig.GROUP_NAME,
			QuartzConfig.cron);
        }
    }

以上就完成了注入Bean的方式,动态添加quartz任务