关于Spring boot框架整合quartz,解决了mapper无法注入的问题

转自https://blog.csdn.net/shasiqq/article/details/80421479

https://blog.csdn.net/li614814/article/details/80543515

我只贴代码:

1.配置pom.xml

<dependency>
     <groupId>org.quartz-scheduler</groupId>
     <artifactId>quartz</artifactId>
     <version>2.2.1</version>
</dependency>
<dependency><!-- 该依赖必加,里面有sping对schedule的支持 -->
     <groupId>org.springframework</groupId>
     <artifactId>spring-context-support</artifactId>
</dependency>

2.先写一个监听器保证项目启动的时候会调用到,我们的定时任务,代码如下

import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;

import com.fjaidata.timer.MyScheduler;

@Configuration
public class SchedulerListener implements ApplicationListener<ContextRefreshedEvent>{
    @Autowired
    public MyScheduler myScheduler;
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        try {
            myScheduler.scheduleJobs();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

}

3.写我们自己的定时器,用来触发我们的任务

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

import com.fjaidata.job.AiArticleJob;
import com.fjaidata.job.SealedBiddingJob;
@Component
public class MyScheduler {
    @Autowired
    SchedulerFactoryBean schedulerFactoryBean;

    static Scheduler scheduler;

    public void scheduleJobs() throws SchedulerException {
        scheduler = schedulerFactoryBean.getScheduler();
        startJob1();
        startJob2();
    }
    
    public static void startJob1() throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(AiArticleJob.class).withIdentity("job1", "group1").build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0 0 8 * * ?");
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                .withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail, cronTrigger);
    }
    
    public static void startJob2() throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(SealedBiddingJob.class).withIdentity("job2", "group1").build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0 0 8 ? * MON,FRI");
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group1")
                .withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail, cronTrigger);
    }
    
    
}

4.定时器

@Configuration
public class SealedBiddingJob implements Job{
    @Autowired
    private SealedBiddingMapper biddingMapper;
    
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {}
}

这是我们会发现总是报空指针的问题

原因:在quartz框架中,Job 是通过反射出来的实例,不受spring的管理。Scheduler现在交给Spring生成,在Spirng-context-support  jar包下org.springframework.scheduling.quartz包中有个SpringBeanJobFactory的类,job实例通过该类的createJobInstance方法创建。根据Scheduler context、job data map and trigger data map填充其属性。但是创建的job实例并没被spring管理,这就需要我们自定义一个类将创建的job添加到applicationContext中,该类需要继承SpringBeanJobFactory,并实现ApplicationContextAware接口。

    ApplicationContextAware接口的作用:Spring容器会检测容器中的所有Bean,如果发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContextAware()方法,调用该方法时,会将容器本身作为参数传给该方法——该方法中的实现部分将Spring传入的参数(容器本身)赋给该类对象的applicationContext实例变量,因此接下来可以通过该applicationContext实例变量来访问容器本身。

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
        ApplicationContextAware {

    private transient AutowireCapableBeanFactory autowireCapablebeanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {
        autowireCapablebeanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        autowireCapablebeanFactory.autowireBean(job);
        return job;
    }
}
@Configuration
public class SchedulerConfig {
    
    @Bean
    public JobFactory jobFactory(ApplicationContext applicationContext)
    {
        AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws Exception {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setOverwriteExistingJobs(true);
        factory.setJobFactory(jobFactory);
        factory.afterPropertiesSet();
        return factory;
    }

}

 

posted on 2019-05-07 17:38  大山008  阅读(1279)  评论(0编辑  收藏  举报