Spring Quartz使用父类构造函数设置基于构造函数的注入

nr7wwzry  于 2022-11-21  发布在  Spring
关注(0)|答案(3)|浏览(211)

我有一个Spring Boot 项目,我想使用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通过构造函数连接适当的依赖项?

vqlkdk9b

vqlkdk9b1#

docs中所述:
此行为的一个后果是作业必须具有无参数构造函数(使用默认JobFactory实现时)。
您实际上使用的是默认的JobFactory,并添加了自动装配功能。我从个人测试中发现,自动装配无法与构造函数注入一起工作。另外,不要使用Spring注解(Component、Service等)标记您的作业,因为它没有任何效果。
要解决您的问题,重构您的作业,使其具有默认的构造函数和带有字段注入的autowire依赖项(也许setter注入也能起作用)。

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
    }
}
rlcwz9us

rlcwz9us2#

我刚刚在这里发布了一个答案,只是普通的quartz有自动装配功能。但是,请注意,你需要有一个无参数的构造函数(在你的情况下使用无参数和参数构造函数)。Quartz使用类名来示例化示例,所以,你的带参数的构造函数将无法工作。
如果您仍然在处理同一个问题,请尝试我的方法,您可以自动连接所需的依赖项,而不是通过super(foo);
https://stackoverflow.com/a/49316580/2931410

m528fe3b

m528fe3b3#

当类不包含默认构造函数时,会出现此问题。
示例:YourJob扩展QuartzJobBean则类应包含默认构造函数。如果使用lombok,请添加**@Component标记与@NoArgsConstructor**。其他所需的Bean应通过@Autowired自动连接到此类

相关问题