解决定时器Quartz中任务调度无法使用Spring自动注入的问题

描述:

需求:使用定时器来实现定时持久化Redis中的数据到Mysql——定时器选择Quartz
问题:使用定时器定义Job时需要使用RedisTemplate对象来操作Redis,一般情况下的使用方式为:

package com.nys.quartz;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

/**
* 定时任务
* @author nysheng
*/
public class JobTest implements Job {
   @Autowired
   private RedisTemplate redisTemplate;
   @Override
   public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
       Object o = redisTemplate.opsForValue().get("test");
       //其他操作..........
   }
}

但这种方式会发生空指针异常:java.lang.NullPointerException 即redisTemplate为null
原因:因为Spring是在启动时就扫描@Autowired并完成注入的,此时被注入的Job实例是唯一的,但Quartz每次调度执行Job时,都是重新实例化的一个Job,这个实例和Spring注入的实例是不同的,所以没有属性,redisTemplate即为空。


解决办法:

自定义工具类继承ApplicationContextAware,直接编写get方法来获取Spring容器中的对象:

package com.nys.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author nysheng
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
    public static Object getBean(String beanName){
        return applicationContext.getBean(beanName);
    }
}

使用方法:直接通过bean的name属性值获取实例

private RedisTemplate redisTemplate= (RedisTemplate)SpringContextUtil.getBean("redisTemplate");

修改后的Job:

package com.nys.quartz;

import com.nys.utils.SpringContextUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * 定时任务
 * @author nysheng
 */
public class JobTest implements Job {
    private RedisTemplate redisTemplate= (RedisTemplate)SpringContextUtil.getBean("redisTemplate");
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Object o = redisTemplate.opsForValue().get("test");
        //其他操作..........
    }
}



你可能感兴趣的:(SSM,编程技术)