2010-11-23 2 views
30

я использую кварц с пружиной и я хочу, чтобы ввести/использовать другой класс в классе работы и я не знаю, как это правильно сделатьКак использовать @Autowired в Quartz Job?

в 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

Ссылка ниже разрешал решение для меня http://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz-job-in-spring/15211030#17394905 – pathfinder 2014-09-14 09:18:00

ответ

10

Не уверен, что это то, что вы хотите, но вы можете передать некоторые значения конфигурации в задание кварца. Я считаю, что в вашем случае вы можете воспользоваться 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, определенное с помощью геттера/сеттера. Вы можете попробовать его определения с java.lang.Class типа, то и есть сделано автоматически (весна будет делать это для вас):

private Class<?> param1; 

// getter & setter 

protected void executeInternal(JobExecutionContext context) throws JobExecutionException { 
    schedulerTask.printSchedulerMessage(); 
    System.out.println("Class injected" + getParam1().getName()); 
}  

Я не проверял, хотя.

+0

I хотите иметь возможность использовать объект DTO и объект домена в задании кварца, и автоустановка здесь не работает, так что вы можете сказать мне, что делать дальше? – 2010-11-24 08:22:06

+2

В вашем вопросе вы написали, что хотите использовать класс, а не объект. В любом случае, какая разница? – 2010-11-24 09:24:26

+0

В руководстве Quartz говорится (как наилучшая практика): «Храните только примитивные типы данных в JobDataMap, чтобы избежать проблем с сериализацией данных в краткосрочной и долгосрочной перспективе». Действительно ли это решение работает хорошо? Благодарю. – aloplop85 2013-09-08 17:10:48

14

В вашем решении вы используете пружину @Автоматическая аннотация в классе, не созданная весной. Ваше решение по-прежнему будет работать, если вы удалите @Autowired аннотацию, потому что Quartz устанавливает свойство, а не Spring.

Quartz попытается установить каждый ключ в JobDataMap как свойство. Например. так как у вас есть ключ «myDao», кварц будет искать метод «setMyDao» и передать значение ключа в этот метод.

Если вы хотите, чтобы Spring ввел весенние бобы в ваши рабочие места, создайте SpringBeanJobFactory и установите это в свой SchedulerFactoryBean с помощью свойства jobFactory в контексте вашей весны.

SpringBeanJobFactory Javadoc:

Применяет контекста планировщика, картографических данных задания и карты данных триггера записи в свойство компонента значения

+6

Для тех, кто интересуется, вы можете найти реализацию `SpringBeanJobFactory` для автоматического автозапуска задания Quartz в этом ответе (включая полный пример): http://stackoverflow.com/a/15211030/787375 – jelies 2013-03-09 07:41:37

8
ApplicationContext springContext = 
    WebApplicationContextUtils.getWebApplicationContext(
     ContextLoaderListener.getCurrentWebApplicationContext().getServletContext() 
    ); 
Bean bean = (Bean) springContext.getBean("beanName"); 
bean.method(); 
2

Как уже упоминалось в inject bean reference into a Quartz job in 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 на какой-то весенней версии, но я протестировал его на 4.2.1.RELEASE, который отлично работал.

0

это мое решение:

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> 

Успехов! :)