Job实现类代码
1 package cn.itcast.quartz; 2 3 import org.quartz.Job; 4 import org.quartz.JobExecutionContext; 5 import org.quartz.JobExecutionException; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.stereotype.Service; 8 9 import cn.itcast.service.HelloServiceImpl; 10 11 /** 12 * @author: 攻城狮小白 13 * @creationTime:2017年11月20日 下午5:21:28 14 */ 15 @Service 16 public class HelloJob implements Job{ 17 18 @Autowired 19 private HelloServiceImpl helloServiceImpl; 20 public void execute(JobExecutionContext context) throws JobExecutionException { 21 helloServiceImpl.sayHello(); 22 } 23 24 }
业务实现类代码
1 package cn.itcast.service; 2 3 import org.springframework.stereotype.Service; 4 5 /** 6 * @author: 攻城狮小白 7 * @creationTime:2017年11月20日 下午5:42:12 8 */ 9 @Service 10 public class HelloServiceImpl { 11 public void sayHello(){ 12 System.out.println("hello quartz..."); 13 } 14 }
spring核心配置文件applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 8 9 <context:component-scan base-package="cn.itcast"></context:component-scan> 10 <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> 11 <property name="jobClass" value="cn.itcast.quartz.HelloJob"></property> 12 </bean> 13 14 <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> 15 <property name="jobDetail" ref="jobDetail"></property> 16 <property name="startDelay" value="3000"></property> 17 <property name="repeatInterval" value="5000"></property> 18 </bean> 19 20 <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 21 <property name="triggers"> 22 <list> 23 <ref bean="simpleTrigger"/> 24 </list> 25 </property> 26 </bean> 27 </beans>
描述:按上面配置的代码执行时,helloServiceImpl对象会无法注入,会报空指针异常。
原因:因为JobDetailFactoryBean中注入的是一个cn.itcast.quartz.HelloJob实现类的全路径,底层会反射创建出一个HelloJob的对象,但是该对象不是由spring管理的,所以业务层的对象无法注入。
解决方案有如下两种
方案一:将如下类JobFactory复制放到自己项目下,然后修改配置文件,并将该JobFactory配置到applicationContext.xml中(详见配置文件第20行和第22行),helloServiceImpl就能够被注入了。
1 package cn.itcast.quartz; 2 3 import org.quartz.spi.TriggerFiredBundle; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 6 import org.springframework.scheduling.quartz.AdaptableJobFactory; 7 import org.springframework.stereotype.Service; 8 9 @Service("jobFactory") 10 public class JobFactory extends AdaptableJobFactory { 11 @Autowired 12 private AutowireCapableBeanFactory capableBeanFactory; 13 @Override 14 protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { 15 // 调用父类的方法 16 Object jobInstance = super.createJobInstance(bundle); 17 // 进行注入 18 capableBeanFactory.autowireBean(jobInstance); 19 return jobInstance; 20 } 21 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 8 9 <context:component-scan base-package="cn.itcast"></context:component-scan> 10 <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> 11 <property name="jobClass" value="cn.itcast.quartz.HelloJob"></property> 12 </bean> 13 14 <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> 15 <property name="jobDetail" ref="jobDetail"></property> 16 <property name="startDelay" value="3000"></property> 17 <property name="repeatInterval" value="5000"></property> 18 </bean> 19 20 <bean id="jobFactory" class="cn.itcast.quartz.JobFactory"></bean> 21 <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 22 <property name="jobFactory" ref="jobFactory"></property> 23 <property name="triggers"> 24 <list> 25 <ref bean="simpleTrigger"/> 26 </list> 27 </property> 28 </bean> 29 </beans>
方案二:在Job实现类中添加下面这行代码即可(这种方式虽然方便,但是当你的Job实现类过多时,需要给每个类都添加该行代码,所以当Job实现类过多的时候建议还是采用方案一,只需要配置一次就OK)
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
1 package cn.itcast.quartz; 2 3 import org.quartz.Job; 4 import org.quartz.JobExecutionContext; 5 import org.quartz.JobExecutionException; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.stereotype.Service; 8 import org.springframework.web.context.support.SpringBeanAutowiringSupport; 9 10 import cn.itcast.service.HelloServiceImpl; 11 12 /** 13 * @author: 攻城狮小白 14 * @creationTime:2017年11月20日 下午5:21:28 15 */ 16 @Service 17 public class HelloJob implements Job{ 18 @Autowired 19 private HelloServiceImpl helloServiceImpl; 20 public void execute(JobExecutionContext context) throws JobExecutionException { 21 SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 22 helloServiceImpl.sayHello(); 23 } 24 }