Spring+Quartz定时任务service注入问题

我自己的解决过程:http://blog.csdn.net/axela30w/article/details/67632242(跟下面两种稍微不一样

 

第一种解决方案:

一般情况下,quartz的job中使用autowired注解注入的对象为空,这时候我们就要使用spring-quartz提供的AdaptableJobFactory类。

自定义一个类:

[java] view plain copy    

  1. public class JobFactory extends AdaptableJobFactory {  
  2.       
  3.     @Autowired  
  4.     private AutowireCapableBeanFactory capableBeanFactory;  
  5.   
  6.     @Override  
  7.     protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {  
  8.         //调用父类的方法  
  9.         Object jobInstance = super.createJobInstance(bundle);  
  10.         //进行注入  
  11.         capableBeanFactory.autowireBean(jobInstance);  
  12.         return jobInstance;  
  13.     }  
  14.       
  15. }  

然后在spring中配置:

 

 

[html] view plain copy    

  1.   
  2.     <bean id="jobFactory" class="com.xx.job.JobFactory">bean>  
  3.     <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  4.         <property name="jobFactory" ref="jobFactory">property>  
  5.     bean>  

这时候,我们在定义类继承job的时候,就可以使用autowired注入service对象了:

 

 

[java] view plain copy    

  1. public class Test1Job implements Job {  
  2.     public final Logger log = Logger.getLogger(this.getClass());  
  3.       
  4.     @Autowired  
  5.     private JobTaskService jobTaskService;  
  6.       
  7.     public void execute(JobExecutionContext context) throws JobExecutionException {  
  8.         //更新上一次执行时间和下一次计划执行时间  
  9.         Date nextProcessTime = context.getNextFireTime();  
  10.         ScheduleJob job = (ScheduleJob) context.getJobDetail().getJobDataMap().get("scheduleJob");  
  11.         job.setNextProcessTime(nextProcessTime);  
  12.         jobTaskService.updateTaskByJobName(job);  
  13.           
  14.         //业务逻辑  
  15.         System.out.println("22222222222222222222:");  
  16.     }  
  17. }  

 

第二种解决方案

 

 

今天想单元测试一下spring中的quartz定时任务,job类的大致结构和下面的SpringQtz1类相似,我的是实现的org.quartz.Job接口,到最后总是发现job类里注入的service为null。一开始还以为spring的配置问题,各种找原因,最后还是确定是没有注入的原因。

就去网上搜搜吧。也找出来一些眉目。简单的理解这个原因是job是在quartz中实例化出来的,不受spring的管理。所以就导致注入不进去了。参考这个文章

http://www.tuicool.com/articles/Qjyamu

找着试试的态度,就按照文章里说的。new一个类

复制代码

public class MyJobFactory extends AdaptableJobFactory {

    //这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;
    
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

复制代码

接下来把他配置到Spring当中去

然后在把org.springframework.scheduling.quartz.SchedulerFactoryBean的jobFactory设置成我们自己的。


  
  

这样就ok了。

 

问题算是解决了吧,但是想着还要自己写一个类,还要配置到其它地方,感觉破坏了quartz的完整性,事情不应该是这样子的。就试着找找其它方法。

 

正好前几天写spring和quartz的例子的时候,一个文章介绍了spring下quartz定时任务的两种方式。博文地址http://kevin19900306.iteye.com/blog/1397744

一个是继承QuartzJobBean,另一个不用继承,单纯的java类。我想QuartzJobBean是spring里的类,这样的话这个方式的定时任务类是否就是spring来管理的。注入应该就没问题了吧。

这是一个很小的项目,实验起来也很简单,就启动,debug。发现还是注入不进去。就接着试第二种方式,debug。惊奇的发现注入没问题了。

到此为止,这个问题已经解决了。当然还是最后一种方式合理简单。

 --------------------------------------------------------------------------------------------------------------------------------

Junit的加入

如果再加上Junit的话,情况可能会再复杂一点。有一个现象就是你如果运行了测试方法,就是你可能看不到定时任务运行。在进行任务类里打断点,也可能不起作用,原因就是junit是另一个单独的线程,

这个线程结束了,就整个结束了,所以可能就轮不到定时任务运行。junit的这一特点,如果你想测试多线程的代码,也可能会得到不是你想要的结果。关于怎么测试多线程,请自行百度。

这里有两个解决方案,第一,像贴出的代码里一样,加入这样的代码,这个代码的作用就是防止junit方法的线程退出。

     System.out.println("请输入信息:");
        Scanner input = new Scanner(System.in);
        int x= input.nextInt();
        System.out.println(x);

第二个方法就是,不加上面的代码,加入下面的代码也可能达到定时任务能正常运行的效果。

@Before
    public void before(){
        System.out.println("============启动前============");
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }

 

还有junit测试类里增加了一个自己手动写scheduler调用job的方法,我试了一下,这种方式的service没法注入。虽然这种方式测试job比较灵活一些。

 

新增加的Junit测试类

复制代码

import com.dupang.quartz.SpringQtz1;
import org.junit.Before;
import org.junit.Test;
import org.quartz.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

import java.io.InputStream;
import java.util.Calendar;
import java.util.Scanner;

/**
 * Created by dupang on 2016/11/15.
 */
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class JunitTest extends AbstractJUnit4SpringContextTests {

    @Before
    public void before(){
        //System.out.println("============启动前============");
        //ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }
    @Test
    public void helloTest(){
        System.out.println("dupang");
        System.out.println("请输入信息:");
        Scanner input = new Scanner(System.in);
        int x= input.nextInt();
        System.out.println(x);
    }

    @Test
    public void schedulerTest() throws SchedulerException {
        SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
        Scheduler sched = schedFact.getScheduler();
        sched.start();

        JobDetail jobDetail = new JobDetail("myJob",Scheduler.DEFAULT_GROUP,SpringQtz1.class);

        SimpleTrigger trigger = new SimpleTrigger("testTrigger", Scheduler.DEFAULT_GROUP);
        trigger.setRepeatCount(10);
        trigger.setRepeatInterval(500);
        trigger.setStartTime(Calendar.getInstance().getTime());

        sched.scheduleJob(jobDetail, trigger);
        System.out.println("请输入信息:");
        Scanner input = new Scanner(System.in);
        int x= input.nextInt();
        System.out.println(x);
    }
}

复制代码

 

 

 

貌似不能上传附件就把所有源码贴过来吧。

目录结构为

Spring+Quartz定时任务service注入问题_第1张图片

pom.xml

 

复制代码




  4.0.0
  war

  test
  test
  test
  1.0-SNAPSHOT
  
    3.0.5.RELEASE
  
  


    
      org.springframework
      spring-context
      ${springframework.version}
    

    
      org.springframework
      spring-context-support
      ${springframework.version}
    

    
      org.springframework
      spring-tx
      ${springframework.version}
    

    
      org.springframework
      spring-web
      ${springframework.version}
    

    
      org.quartz-scheduler
      quartz
      1.8.5
    

    
      junit
      junit
      4.12
    
    
      org.springframework
      spring-test
      ${springframework.version}
    
  

复制代码

 

 

 

web.xml

复制代码




  
    org.springframework.web.context.ContextLoaderListener
  

        

复制代码

applicationContext.xml

复制代码




  

  

  
  
  
    
    
    
    
      simple is the beat
    
    
  
  
  
  
  
  
    
      
    
      
      execute
    
  

  
  
    
    
  

  
  
    
      
        
      
    
  

复制代码

MyJobFactory

复制代码

package com.dupang.util;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;

/**
 * Created by dupang on 2016/11/14.
 */
public class MyJobFactory extends AdaptableJobFactory {

    //这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

复制代码

HelloService

复制代码

package com.dupang.service;

/**
 * Created by dupang on 2016/11/14.
 */
public interface HelloService {

    void sayHello(String name);
}

复制代码

HelloServiceImpl
 

复制代码

package com.dupang.impl;

import com.dupang.service.HelloService;
import com.sun.javafx.collections.SourceAdapterChange;
import org.springframework.stereotype.Service;

/**
 * Created by dupang on 2016/11/14.
 */
@Service
public class HelloServiceImpl implements HelloService {
    public void sayHello(String name) {
        System.out.println("Hello to"+ name);
    }
}

复制代码

 
SpringQtz1

复制代码

package com.dupang.quartz;

import com.dupang.service.HelloService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import javax.annotation.Resource;
import java.util.Date;

/**
 * Created by Administrator on 2016/11/9.
 */
public class SpringQtz1 extends QuartzJobBean {

    @Resource
    HelloService helloService;
    private static int counter = 0;
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        helloService.sayHello("dupang");
    }
}

复制代码

SpringQtz2

复制代码

package com.dupang.quartz;

import com.dupang.service.HelloService;

import javax.annotation.Resource;
import java.util.Date;

/**
 * Created by Administrator on 2016/11/9.
 */
public class SpringQtz2 {
    private static int counter = 0;
    @Resource
    HelloService helloService;
    protected void execute() {
        helloService.sayHello("dupang");
    }
}

复制代码

 

最后,我以前也用过quartz的定时任务,当时里面也有service,我都不记得遇到有注入的问题,后来翻了一下代码,原来就没有用到注入,它是直接getBean()的方式来获取service的。如下图

 

 

你可能感兴趣的:(Spring)