簡體   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