Spring Quartz Настройка инжектора на основе конструктора с помощью конструктора родительского класса
У меня есть весенний загрузочный проект, с которым я хочу использовать кварц для выполнения определенных заданий в определенное время. У меня есть этот макет класса:
abstract public class AbstractFoo {
protected final FooB fooB;
public AbstractFoo(FooB fooB) {
this.fooB = fooB;
}
}
@Service
public class SomeJob extends AbstractFoo implements Job {
public SomeJob(FooB fooB) {
super(fooB);
}
@Override
public void execute(final JobExecutionContext context) throws JobExecutionException {
//do stuff
}
}
Однако, когда я запускаю это задание, я получаю следующую ошибку:
2017-12-06 14:18:01,383 ERROR --- [quartz-jobs] org.quartz.core.ErrorLogger : An error occured instantiating job to be executed. job= 'jobGroup.someJob'
org.quartz.SchedulerException: Job instantiation failed
at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:45)
at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)
Caused by: java.lang.InstantiationException: com.jobs.SomeJob
at java.lang.Class.newInstance(Class.java:427)
at org.springframework.scheduling.quartz.AdaptableJobFactory.createJobInstance(AdaptableJobFactory.java:58)
at org.springframework.scheduling.quartz.SpringBeanJobFactory.createJobInstance(SpringBeanJobFactory.java:74)
at com.config.AutowiringSpringBeanJobFactory.createJobInstance(AutowiringSpringBeanJobFactory.java:27)
at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:41)
... 2 common frames omitted
Caused by: java.lang.NoSuchMethodException: com.jobs.SomeJob.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 6 common frames omitted
У меня уже есть завод по производству автопроводов, вот так:
public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
ApplicationContextAware {
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);
beanFactory.autowireBean(job);
return job;
}
}
И вот мой кварцевый конфиг:
@Configuration
public class QuartzConfig {
@Autowired
private DataSource dataSource;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private ApplicationContext applicationContext;
@Bean
public SchedulerFactoryBean quartzScheduler() {
SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean();
quartzScheduler.setDataSource(dataSource);
quartzScheduler.setTransactionManager(transactionManager);
quartzScheduler.setOverwriteExistingJobs(true);
quartzScheduler.setSchedulerName("quartz-jobs");
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
quartzScheduler.setJobFactory(jobFactory);
quartzScheduler.setQuartzProperties(quartzProperties());
Trigger[] triggers = {someJobTrigger().getObject();
quartzScheduler.setTriggers(triggers);
return quartzScheduler;
}
@Bean
public CronTriggerFactoryBean someJobTrigger() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(someJob().getObject());
cronTriggerFactoryBean.setCronExpression(cronExp);
cronTriggerFactoryBean.setGroup(someGroup);
return cronTriggerFactoryBean;
}
@Bean
public JobDetailFactoryBean someJob() {
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(SomeJob.class);
jobDetailFactory.setGroup(someGroup);
jobDetailFactory.setDurability(true);
return jobDetailFactory;
}
@Bean
public Properties quartzProperties() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
Properties properties = null;
try {
propertiesFactoryBean.afterPropertiesSet();
properties = propertiesFactoryBean.getObject();
} catch (IOException e) {
}
return properties;
}
}
Как мне заставить Quartz подключаться в соответствующих зависимостях через конструктор?
3 ответа
Как указано в документации:
Одним из последствий такого поведения является тот факт, что задания должны иметь конструктор без аргументов (при использовании реализации JobFactory по умолчанию).
Вы, по сути, используете JobFactory по умолчанию с добавленной возможностью автоматического подключения Из моих личных тестов я обнаружил, что автоматическое подключение не будет работать с инжектором конструктора. Также не помечайте свою работу аннотациями Spring (Component, Service, ect), так как это не имеет никакого эффекта.
Чтобы решить вашу проблему, сделайте рефакторинг вашей работы, чтобы иметь зависимости конструктора по умолчанию и автоматическую привязку с инжекцией поля (возможно, инсталляция установки также будет работать).
abstract public class AbstractFoo {
@Autowired
protected FooB fooB;
}
public class SomeJob extends AbstractFoo implements Job {
@Override
public void execute(final JobExecutionContext context) throws JobExecutionException {
//do stuff
}
}
Я только что опубликовал здесь ответ с обычным кварцем с возможностью автоматической проводки. Тем не менее, обратите внимание, что вам нужен конструктор без аргументов (в вашем случае используйте конструктор без аргументов и аргумент). Кварц использует имя класса для создания экземпляра, поэтому ваш конструктор с аргументом работать не будет.
Если вы все еще работаете над той же проблемой, попробуйте мой подход, при котором вы можете автоматически связать требуемую зависимость, а не переходить через super(foo);
/questions/5365933/dobavit-ssyilku-na-komponent-v-rabotu-quartz-vesnoj/5365966#5365966
Эта проблема возникает, когда класс не содержит конструктора по умолчанию.
Пример: YourJob расширяет QuartzJobBean , тогда класс должен содержать конструктор по умолчанию. Добавьте аннотацию @Component и @NoArgsConstructor , если вы используете ломбок. Другие необходимые bean-компоненты должны быть автоматически подключены к этому классу с помощью @Autowired.