spring 如何在 Quartz 作业中使用 @Autowired?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4258313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use @Autowired in a Quartz Job?
提问by Mahmoud Saleh
i am using quartz with spring and i want to inject/use another class in the job class and i don't know how to do it correctly
我正在使用带有弹簧的石英,我想在作业类中注入/使用另一个类,但我不知道如何正确执行
the xml:
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>
the quartz job:
石英工作:
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();
}
}
the task to be executed:
要执行的任务:
package com.mkyong.quartz;
public class SchedulerTask {
public void printSchedulerMessage() {
System.out.println("Struts 2 + Spring + Quartz ......");
}
}
i want to inject another DTO class that deals with Database in the task class to do some database work in the task, how to do that ?
我想在任务类中注入另一个处理数据库的 DTO 类来在任务中做一些数据库工作,怎么做?
采纳答案by Grzegorz Oledzki
Not sure if this is what you want, but you can pass some configuration values to the Quartz job. I believe in your case you could take advantage of the jobDataAsMapproperty you already set up, e.g.:
不确定这是否是您想要的,但您可以将一些配置值传递给 Quartz 作业。我相信在您的情况下,您可以利用jobDataAsMap您已经设置的属性,例如:
<property name="jobDataAsMap">
<map>
<entry key="schedulerTask" value-ref="schedulerTask" />
<entry key="param1" value="com.custom.package.ClassName"/>
</map>
</property>
Then you should be able to access it in your actual Java code in manual way:
然后您应该能够以手动方式在您的实际 Java 代码中访问它:
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
schedulerTask.printSchedulerMessage();
System.out.println(context.getJobDetail().getJobDataMap().getString("param1"));
}
Or using the magic Spring approach - have the param1property defined with getter/setter. You could try defining it with java.lang.Classtype then and have the done automatically (Spring would do it for you):
或者使用神奇的 Spring 方法 -param1使用 getter/setter 定义属性。您可以尝试使用java.lang.Classtype定义它,然后自动完成(Spring 会为您完成):
private Class<?> param1;
// getter & setter
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
schedulerTask.printSchedulerMessage();
System.out.println("Class injected" + getParam1().getName());
}
I haven't tested it though.
不过我还没有测试过。
回答by Kieren Dixon
In your solution you are using the spring @Autowired annotation in a class that is not instantiated by Spring. Your solution will still work if you remove the @Autowired annotation because Quartz is setting the property, not Spring.
在您的解决方案中,您在未由 Spring 实例化的类中使用 spring @Autowired 注释。如果您删除 @Autowired 注释,您的解决方案仍然有效,因为 Quartz 正在设置该属性,而不是 Spring。
Quartz will try to set every key within the JobDataMap as a property. E.g. since you have a key "myDao" Quartz will look for a method called "setMyDao" and pass the key's value into that method.
Quartz 会尝试将 JobDataMap 中的每个键设置为一个属性。例如,由于您有一个键“myDao”,Quartz 将寻找一个名为“setMyDao”的方法并将键的值传递给该方法。
If you want Spring to inject spring beans into your jobs, create a SpringBeanJobFactory and set this into your SchedulerFactoryBean with the jobFactoryproperty within your spring context.
如果您希望 Spring 将 spring bean 注入您的作业,请创建一个 SpringBeanJobFactory 并将其设置到您的 SchedulerFactoryBean 中,并在您的 spring 上下文中使用jobFactory属性。
SpringBeanJobFactory javadoc:
SpringBeanJobFactory javadoc:
Applies scheduler context, job data map and trigger data map entries as bean property values
应用调度程序上下文、作业数据映射和触发器数据映射条目作为 bean 属性值
回答by Damian
ApplicationContext springContext =
WebApplicationContextUtils.getWebApplicationContext(
ContextLoaderListener.getCurrentWebApplicationContext().getServletContext()
);
Bean bean = (Bean) springContext.getBean("beanName");
bean.method();
回答by Alireza Fattahi
As mentioned in inject bean reference into a Quartz job in Spring?you can use spring SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
正如在 Spring中将bean 引用注入到 Quartz 作业中所述?你可以用弹簧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();
}
}
As mentioned it may not wotk on some spring version but I have tested it on 4.2.1.RELEASE which worked fine.
如前所述,它可能不适用于某些 spring 版本,但我已经在 4.2.1.RELEASE 上对其进行了测试,效果很好。
回答by martin
this is my solution:
这是我的解决方案:
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;
}
}
then config the class of MySpringBeanJobFactory in the xml:
然后在xml中配置MySpringBeanJobFactory的类:
<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>
Good luck ! :)
祝你好运 !:)

