2017-09-26 49 views
3

我试着在春季使用石英调度器。当配置多个作业时,我会得到下面的异常弹簧引导不工作石英多个作业自动装配

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); 
} 

的服务类有春天JPA回购。 问题的根本原因是以下自动布线服务。如果我从两个作业中删除下面的自动布线服务,那么它工作正常。

@Autowired private service service;

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

回答

0

jobTrigger方法期望作为参数a JobDetail但传递的豆类型为JobDetailFactoryBean

也许你应该做出以下改变或类似的东西。

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

和job2一样。

顺便提一下, 你提到Spring - v1.5。你真的使用哪个版本的Spring?

+0

“JobDetailFactoryBean提供豆式的用法配置的JobDetail实例”从http: //www.baeldung.com/spring-quartz-schedule。我的糟糕的春天版本是4.2.9 – Zire

+0

是的,但是你正试图将'JobDetailFactoryBean' bean注入类型为'JobDetail'的参数。这怎么可能工作?我认为你应该使用'JobDetailFactoryBean'的getObject()方法得到实际的jobDetail。 – lzagkaretos

+0

我猜春天手柄。如果不是,它甚至不适用于单一工作。我只有在有多个工作时才会遇到问题。我可以在网上找到的所有文档和文章都使用相同的方式。如果我删除autowired服务,并使用应用程序上下文手动注入bean,我不明白这个问题。 – Zire

0

您试图在Spring 4.2中使用spring引导配置。

尝试改变工作类中的下列方法如下

@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(); 
} 

而且采用弹簧4.3,因为你需要

@Autowired 
List<Trigger> triggers; 

我相信集自动装配工作只在4.3

0

我所面临的同样的问题,并经过一番努力后,我能够解决它。它可能是在作业类中使用的注释中实现的。我看到你正在使用@Component,就像我的情况一样。相反,石英调度程序配置使用@Configuration标记进行注释。

解决方案是使用@Configuration标签标记作业。我的猜测是@Bean@Component构造的注释类不完整构造/映射在@Configuration注释的初始化阶段。

1

这是您引用的用于在一个配置文件中处理多个Quartz作业的http://www.baeldung.com/spring-quartz-schedule的修改版本。为了简便起见,我没有包括整个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) { 

    ... 
} 
+0

这正是我所需要的。非常感谢! – rocotocloc