Как использовать @Autowired в Quartz Job?
Я использую кварц с spring
и я хочу добавить/использовать другой класс в классе заданий
и я не знаю, как это сделать правильно
xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- Scheduler task -->
<bean name="schedulerTask" class="com.mkyong.quartz.SchedulerTask" />
<!-- Scheduler job -->
<bean name="schedulerJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.mkyong.quartz.SchedulerJob" />
<property name="jobDataAsMap">
<map>
<entry key="schedulerTask" value-ref="schedulerTask" />
</map>
</property>
</bean>
<!-- Cron Trigger -->
<bean id="cronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="schedulerJob" />
<property name="cronExpression" value="0/10 * * * * ?" />
</bean>
<!-- Scheduler -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="schedulerJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
</beans>
задание кварца:
package com.mkyong.quartz;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class SchedulerJob extends QuartzJobBean
{
private SchedulerTask schedulerTask;
public void setSchedulerTask(SchedulerTask schedulerTask) {
this.schedulerTask = schedulerTask;
}
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
schedulerTask.printSchedulerMessage();
}
}
выполняемая задача:
package com.mkyong.quartz;
public class SchedulerTask {
public void printSchedulerMessage() {
System.out.println("Struts 2 + Spring + Quartz ......");
}
}
Я хочу добавить еще один класс DTO, который имеет дело с базой данных в классе задачи
для выполнения какой-либо работы с базой данных в задаче, как это сделать?
Ответы
Ответ 1
Не уверен, что это то, что вы хотите, но вы можете передать некоторые значения конфигурации в задание Quartz. Я полагаю, что в вашем случае вы можете воспользоваться уже установленным свойством jobDataAsMap
, например:
<property name="jobDataAsMap">
<map>
<entry key="schedulerTask" value-ref="schedulerTask" />
<entry key="param1" value="com.custom.package.ClassName"/>
</map>
</property>
Затем вы сможете получить доступ к нему в своем Java-коде вручную:
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
schedulerTask.printSchedulerMessage();
System.out.println(context.getJobDetail().getJobDataMap().getString("param1"));
}
Или используя магический подход Spring - имеют свойство param1
, определенное с помощью метода getter/setter. Вы можете попробовать определить его с типом java.lang.Class
и затем сделать это автоматически (Spring сделает это для вас):
private Class<?> param1;
// getter & setter
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
schedulerTask.printSchedulerMessage();
System.out.println("Class injected" + getParam1().getName());
}
Я еще не тестировал его.
Ответ 2
В вашем решении вы используете аннотацию spring @Autowired в классе, который не создан Spring. Ваше решение по-прежнему будет работать, если вы удалите @Autowired аннотацию, потому что Quartz устанавливает свойство, а не Spring.
Quartz попытается установить каждый ключ в JobDataMap как свойство. Например. так как у вас есть ключ "myDao", кварц будет искать метод под названием "setMyDao" и передать значение ключа в этот метод.
Если вы хотите, чтобы spring вводил spring beans в ваши задания, создайте SpringBeanJobFactory и установите его в свой SchedulerFactoryBean с помощью свойства jobFactory в контексте spring.
SpringBeanJobFactory javadoc:
Применяет контекст планировщика, карту данных заданий и данные карты данных триггера как значения свойств bean
Ответ 3
ApplicationContext springContext =
WebApplicationContextUtils.getWebApplicationContext(
ContextLoaderListener.getCurrentWebApplicationContext().getServletContext()
);
Bean bean = (Bean) springContext.getBean("beanName");
bean.method();
Ответ 4
Как упоминалось в вставить ссылку bean в задание кварца в Spring?, вы можете использовать spring SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
@Named
public class SampleJob implements Job {
@Inject
private AService aService;
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
//Do injection with spring
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
aService.doIt();
}
}
Как уже упоминалось, он не может быть wotk в некоторой версии spring, но я протестировал его на 4.2.1.RELEASE, который отлично работал.
Ответ 5
это мое решение:
public class MySpringBeanJobFactory extends
org.springframework.scheduling.quartz.SpringBeanJobFactory implements
ApplicationContextAware {
private ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.ctx = applicationContext;
}
@Override
protected Object createJobInstance(TriggerFiredBundle bundle)
throws Exception {
Object jobInstance = super.createJobInstance(bundle);
ctx.getAutowireCapableBeanFactory().autowireBean(jobInstance);
return jobInstance;
}
}
затем настройте класс MySpringBeanJobFactory в xml:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory">
<bean class="com.xxxx.MySpringBeanJobFactory" />
</property>
<property name="configLocation" value="classpath:quartz.properties" />
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
Удачи!:)