springframework simpletriggerfactorybean quartzjobbean quartz org mkyong job example annotation spring spring-mvc quartz-scheduler

spring - simpletriggerfactorybean - ¿Cómo usar @Autowired en un trabajo de Quartz?



spring quartz annotation example (5)

Estoy usando cuarzo con resorte y quiero inyectar / usar otra clase en la clase de trabajo y no sé cómo hacerlo correctamente

el 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>

el trabajo de cuarzo:

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(); } }

la tarea que se ejecutará:

package com.mkyong.quartz; public class SchedulerTask { public void printSchedulerMessage() { System.out.println("Struts 2 + Spring + Quartz ......"); } }

Quiero inyectar otra clase de DTO que se ocupe de la Base de datos en la clase de tareas para hacer un trabajo de base de datos en la tarea, ¿cómo hacer eso?


Como se menciona en la referencia inyectar bean en un trabajo de cuarzo en primavera? puede usar 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(); } }

Como se mencionó, puede que no funcione en alguna versión de primavera, pero lo he probado en 4.2.1.RELEASE, que funcionó bien.


En su solución, está utilizando la anotación Spring @Autowired en una clase que Spring no ha creado una instancia. Su solución seguirá funcionando si elimina la anotación @Autowired porque Quartz está configurando la propiedad, no Spring.

Quartz intentará establecer cada clave dentro de JobDataMap como una propiedad. Por ejemplo, dado que tiene una clave "myDao" Quartz buscará un método llamado "setMyDao" y pasará el valor de la clave a ese método.

Si desea que Spring inyecte los granos de primavera en sus trabajos, cree un SpringBeanJobFactory y configúrelo en su SchedulerFactoryBean con la propiedad jobFactory dentro de su contexto de primavera.

SpringBeanJobFactory javadoc:

Aplica el contexto del planificador, el mapa de datos del trabajo y dispara las entradas del mapa de datos como valores de propiedades del frijol


No estoy seguro de si esto es lo que quiere, pero puede pasar algunos valores de configuración al trabajo de Quartz. Creo que en su caso podría aprovechar la propiedad jobDataAsMap que ya configuró, por ejemplo:

<property name="jobDataAsMap"> <map> <entry key="schedulerTask" value-ref="schedulerTask" /> <entry key="param1" value="com.custom.package.ClassName"/> </map> </property>

Entonces debería poder acceder a él en su código real de Java de forma manual:

protected void executeInternal(JobExecutionContext context) throws JobExecutionException { schedulerTask.printSchedulerMessage(); System.out.println(context.getJobDetail().getJobDataMap().getString("param1")); }

O utilizando el enfoque mágico de Spring: tiene la propiedad param1 definida con getter / setter. Podría intentar definirlo con java.lang.Class y luego hacer el comando automáticamente (Spring lo haría por usted):

private Class<?> param1; // getter & setter protected void executeInternal(JobExecutionContext context) throws JobExecutionException { schedulerTask.printSchedulerMessage(); System.out.println("Class injected" + getParam1().getName()); }

Aunque no lo he probado.


esta es mi solución:

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

luego configura la clase de MySpringBeanJobFactory en el 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>

Buena suerte ! :)


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