繁体   English   中英

在石英作业中使用@Autowired 服务

[英]Using @Autowired service in quartz job

我正在使用 spring 引导,并且我有一项服务可以从数据库存储/检索一些数据。 我想使用使用我的服务的石英作业。 我尝试了许多来自互联网的建议,将石英与 spring 引导集成,但它不起作用。 你能帮我吗?
这是我的代码:
1)我在 pom.xml 中添加了 org.quartz-scheduler 作为依赖项:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>

    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
    </dependency>
</dependencies>

2)这是我的 application.properties 配置为使用 mysql 作为我的服务的数据库:


    server.port=8281

    spring.datasource.driverClassName=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/mydb
    spring.datasource.username=myusername
    spring.datasource.password=mypassword

3)这是我的服务:


    @Service
    public class ReportService {

        JdbcTemplate jdbcTemplate;

        public ReportService(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }

        public List getPendingReports() {
            String sql = "SELECT * FROM report WHERE status = '" + ReportStatus.PENDING.name() +"'";
            ReportMapper reportsMapper = new ReportMapper();
            List reports = jdbcTemplate.query(sql, reportsMapper);
            return reports;
        }
    }

4)调度器class:


    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.SimpleTrigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;

    public class ReportScheduler {

        public void scanAndUpdateReports() {
            SchedulerFactory sf = new StdSchedulerFactory();
            try {
                Scheduler scheduler = sf.getScheduler();
                scheduler.start();

                JobDetail job = JobBuilder.newJob(ReportsJob.class)
                          .withIdentity("reportsJob")
                          .build();

                SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                          .withIdentity("reportsTrigger")
                          .startNow()
                          .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                                  .withIntervalInSeconds(60).repeatForever())
                          .build();

                scheduler.scheduleJob(job, trigger);
            } catch (SchedulerException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

5)我的工作 class 我想自动连接 ReportService,但它是 null:


    public class ReportsJob implements Job {

        @Autowired
        ReportService reportService; //this doesn't work (it is null) 

        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            List reports = reportService.getPendingReports();
            System.out.println("Reports:\n"+reports);
        }
    }

6)现在我正在从 main 方法调用调度程序:


    @SpringBootApplication
    public class ReportAppBeApplication {

        public static void main(String[] args) {
            SpringApplication.run(ReportAppBeApplication.class, args);

            ReportScheduler rs = new ReportScheduler();
            rs.scanAndUpdateReports();
        }

    }

它是 null 因为@Autowired仅适用于@Component@Repository@Service注释的 class。 注释您的ReportJob class 并确保存储 class 的 map 包含在启动时的component scan中。 您可以使用 map 进行扫描:

@ComponentScan(basePackages={"folderOfReportJob"})

此注解应添加到@Configuration@SpringBootApplication注解的 class 中。

编辑:

如果你不想让你的工作成为一个组件,你也可以通过ApplicationContext class 手动获取 bean。 它是这样的:

private static ApplicationContext ac;
ReportService reportService = ac.getBean(ReportService.class);

我碰巧找到了一个关于功能实现的中文博客。 我可以说您正在尝试实现类似spring-boot-starter-quartz东西。

总而言之,您应该定义自己的QuartzJobFactory来修改createJobInstance方法,将autowireBean添加到新创建的 JobDetail 实例。

就像是,

JobDetail job = JobBuilder.newJob(ReportsJob.class)
                          .withIdentity("reportsJob")
                          .build();
// Pseudocode here
autowiredBean(job);

工作示例,

    @Component("quartzJobFactory")
    public static class QuartzJobFactory extends AdaptableJobFactory {

        private final AutowireCapableBeanFactory capableBeanFactory;

        public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
            this.capableBeanFactory = capableBeanFactory;
        }

        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            //调用父类的方法,把Job注入到spring中
            Object jobInstance = super.createJobInstance(bundle);
            capableBeanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }
@Configuration
class Configuration {
    @Bean(name = "scheduler")
    public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setJobFactory(quartzJobFactory);
        factoryBean.afterPropertiesSet();
        Scheduler scheduler = factoryBean.getScheduler();
        scheduler.start();
        return scheduler;
    }
}

全文在这里: https://www.cnblogs.com/supiaopiao/p/14953978.html

就我而言,我添加了注释@DisallowConcurrentExecution。 之后,我可以顺利访问自动接线服务。

import org.quartz.DisallowConcurrentExecution;

@DisallowConcurrentExecution
public class InvoiceJob implements Job {
   @Autowired
   private RuntimeConfigurationService runtimeConfigurationService;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM