6

我正在尝试在春季使用石英调度程序。配置多个作业时出现以下异常

Job2 中方法 jobTrigger 的参数 0 需要一个无法找到的 'org.quartz.JobDetail' 类型的 bean。

石英 - v2.3,弹簧 - v4.2.x

配置类

@Configuration
 public class SchedulerConfig {

private static final Logger LOG = LoggerFactory.getLogger(SchedulerConfig.class);

@Autowired
List<Trigger> triggers;

@Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
    AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
    jobFactory.setApplicationContext(applicationContext);
    return jobFactory;
}

@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory)  throws IOException {
    SchedulerFactoryBean factory = new SchedulerFactoryBean();
          factory.setAutoStartup(true);
    factory.setJobFactory(jobFactory);
         factory.setQuartzProperties(quartzProperties());
    if (triggers != null && !triggers.isEmpty()) {
         LOG.info("starting jobs... Total Triggers - " + triggers.size());
        factory.setTriggers(triggers.toArray(new Trigger[triggers.size()]));
    }

    return factory;
}

@Bean
public Properties quartzProperties() throws IOException {
    PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
    propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
    propertiesFactoryBean.afterPropertiesSet();
    return propertiesFactoryBean.getObject();
}


public static CronTriggerFactoryBean createCronTrigger(JobDetail jobDetail, String cronExpression) {
    CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
    factoryBean.setJobDetail(jobDetail);
    factoryBean.setCronExpression(cronExpression);
    factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
    return factoryBean;
}

public static JobDetailFactoryBean createJobDetail(Class jobClass) {
    JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
    factoryBean.setJobClass(jobClass);
    factoryBean.setDurability(true);
    return factoryBean;
}

SpringBeanJobFactory

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

private static final Logger LOG = LoggerFactory.getLogger(AutowiringSpringBeanJobFactory.class);

private transient AutowireCapableBeanFactory beanFactory;

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

@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
    final Object job = super.createJobInstance(bundle);
    LOG.info("create job instance");
    beanFactory.autowireBean(job);
    return job;
}

}

工作 1

@Component
@DisallowConcurrentExecution
public class Job1 implements Job {

private final Logger log = LoggerFactory.getLogger(this.getClass());

@Value("${schedule}")
private String frequency;

@Autowired
private Service service;

@Override
public void execute(JobExecutionContext jobExecutionContext) {
    log.info("execute");
}

@Bean(name = "jobBean1")
public JobDetailFactoryBean job() {
    return SchedulerConfig.createJobDetail(this.getClass());
}

@Bean(name = "jobBean1Trigger")
public CronTriggerFactoryBean jobTrigger(@Qualifier("jobBean1")JobDetail jobDetail) {
    return SchedulerConfig.createCronTrigger(jobDetail, frequency);
}

工作 2

@Component
@DisallowConcurrentExecution
public class Job2 implements Job {

private final Logger log = LoggerFactory.getLogger(this.getClass());

@Value("${schedule}")
private String frequency;

@Autowired
private Service service;

@Override
public void execute(JobExecutionContext jobExecutionContext) {
    log.info("execute");
}

@Bean(name = "jobBean2")
public JobDetailFactoryBean job() {
    return SchedulerConfig.createJobDetail(this.getClass());
}

@Bean(name = "jobBean2Trigger")
public CronTriggerFactoryBean jobTrigger(@Qualifier("jobBean2")JobDetail jobDetail) {
    return SchedulerConfig.createCronTrigger(jobDetail, frequency);
}

Service 类具有 Spring JPA 存储库。问题的根本原因是以下自动接线服务。如果我从这两个作业中删除以下自动接线服务,它工作正常。

@Autowired 私人服务服务;

如果这个自动装配的 bean 只有一项工作,那么也不例外。如何使用相同的自动装配依赖项配置多个作业?这个问题是什么原因造成的?

4

4 回答 4

4

这是您引用的http://www.baeldung.com/spring-quartz-schedule的修改版本,用于在一个配置文件中处理多个 Quartz 作业。为简洁起见,我不包括整个 QrtzSheduler 类,只是替换调度程序方法和在触发器中使用 @Qualifier 引用:

...
@Bean
public Scheduler scheduler(Map<String, JobDetail> jobMap, Set<? extends Trigger> triggers) throws SchedulerException, IOException {

    StdSchedulerFactory factory = new StdSchedulerFactory();
    factory.initialize(new ClassPathResource("quartz.properties").getInputStream());

    logger.debug("Getting a handle to the Scheduler");
    Scheduler scheduler = factory.getScheduler();
    scheduler.setJobFactory(springBeanJobFactory());
    Map<JobDetail,Set<? extends Trigger>> triggersAndJobs = new HashMap<JobDetail,Set<? extends Trigger>>;
    for(JobDetail jobDetail : jobMap.getValues()){
        for(Trigger trigger : triggers){
            if(trigger.getJobKey().equals(jobDetail.getKey())){
               Set<Trigger> set = new HashSet<>();
               set.add(trigger);
               triggerAndJobs.put(jobDetail,set);
            }
        }
    }
    scheduler.scheduleJobs(triggersAndJobs, false);

    logger.debug("Starting Scheduler threads");
    scheduler.start();
    return scheduler;
}

@Bean(name="jobOne")
public JobDetail jobDetailOne() {

    ...
}

@Bean(name="jobTwo")
public JobDetail jobDetailTwo() {

   ...
}

@Bean
public Trigger triggerOne(@Qualifier("jobOne")JobDetail jobDetail) {

   ...
}

@Bean
public Trigger triggerTwo(@Qualifier("jobTwo")JobDetail jobDetail) {

   ...
}
于 2018-01-31T16:31:48.147 回答
1

您正在尝试将 Spring Boot 配置与 Spring 4.2 一起使用。

尝试在 Job 类中更改以下方法,如下所示

@Bean(name = "jobBean1")
public JobDetail job() {
    return SchedulerConfig.createJobDetail(this.getClass()).getObject();
}

@Bean(name = "jobBean1Trigger")
public CronTrigger jobTrigger(@Qualifier("jobBean1")JobDetail jobDetail) {
    return SchedulerConfig.createCronTrigger(jobDetail, frequency).getObject();
}

也使用 spring 4.3,因为你需要

@Autowired
List<Trigger> triggers;

我相信 Collection Autowire 仅适用于 4.3

于 2017-11-08T19:06:59.027 回答
1

我遇到了同样的问题,经过一番挣扎后,我能够解决它。它可能与作业类中使用的注释有关。我看到您正在使用@Component,就像我的情况一样。相反,石英调度程序配置使用@Configuration标签进行注释。

解决方案是用@Configuration标签注释你的工作。我的猜测是,在带注释的类中@Bean构造的 ' 在初始化带注释的@Component类的阶段没有完全构造/映射。@Configuration

于 2017-11-15T14:32:30.030 回答
0

我有同样的问题,但现在解决了

package com.crif.credity.config;

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 class SchedulerJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
    private AutowireCapableBeanFactory beanFacotry;

    @Override
    protected Object createJobInstance(TriggerFiredBundle triggerBundle) throws Exception {
        Object createJobInstance = super.createJobInstance(triggerBundle);
        beanFacotry.autowireBean(createJobInstance);
        return createJobInstance;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        beanFacotry = applicationContext.getAutowireCapableBeanFactory();
    }

}

在配置java文件中你可以在bean下面创建

@Autowired
    private ApplicationContext applicationContext;

/** The data source. */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerJobFactory jobFactory = new SchedulerJobFactory();
        jobFactory.setApplicationContext(applicationContext);


        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setOverwriteExistingJobs(true);     
        factoryBean.setJobFactory(jobFactory);
        return factoryBean;
    }

在此之后执行作业类。你可以使用自动连线

package com.crif.credity.jobs;




public class Test implements Job  {

    @Autowired 
    private BatchClientService batchClientService;



    @Override
public void execute(JobExecutionContext context) throws JobExecutionException{
        try {
            batchClientService.executeJob(CredityJob.NEWSCHECK, instanceId);
        } catch (Exception ex) {
            LOG.info(ex.getMessage());
        }
    }

}
于 2020-05-29T14:46:52.907 回答