spring的TimerTask注入service为空的解决办法之一

因项目需求需要执行定时任务,写完后一直报空指针异常,解决方式如下:

思路来自:https://blog.youkuaiyun.com/m912595719/article/details/68945990

1、创建任务类,继承TimerTask类

package com.mes.web.controller.llm.Task;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;

import com.mes.entity.check.PatrolCheck;
import com.mes.entity.check.ReportCheck;
import com.mes.entity.check.TreeCheck;
import com.mes.entity.llm.FillRecord;
import com.mes.entity.warning.Warning;
import com.mes.service.llm.ChartLlmService;
import com.mes.service.warning.WarningService;
import com.mes.utils.PushExample;

/**
 * 执行任务
 * @Title:RunTask
 * @Package com.mes.web.controller.llm.Task
 * @author llm
 * @date 2019年6月6日
 * @version 1.0
 */
public class RankTask extends TimerTask{

	private ChartLlmService chartLlmService;
	private WarningService warningService;
	
	public RankTask(ChartLlmService chartLlmService, WarningService warningService){
		this.chartLlmService = chartLlmService;
		this.warningService = warningService;
	}
	
	public RankTask(){
		super();
	}
	
	/**       
	 *  质检填报查询  
	 */
	@Override
	public void run() {
	
		//查询质检部门员工的权限
		List<FillRecord> list = chartLlmService.selectMenuByDepartment();
        System.out.pringln(list);
	}
}

2、实现JAVA EE的监听接口,定时调用任务类

package com.mes.web.controller.llm.Task;

import java.util.Timer;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.web.context.support.WebApplicationContextUtils;

import com.mes.service.llm.ChartLlmService;
import com.mes.service.warning.WarningService;

/**
 * 
 * @Title:RankTaskListener
 * @Package com.mes.web.controller.llm.Task
 * @author llm
 * @date 2019年6月6日
 * @version 1.0
 */
public class RankTaskListener implements ServletContextListener{

	Timer timer = null;
	/**       
	 * 监听任务
	 * @param sce    
	 */
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		//通过工具类获取spring容器的引用
		ChartLlmService chartLlmService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(ChartLlmService.class);
		WarningService warningService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(WarningService.class);
		timer = new Timer(true);
		//参数内容(1、定时任务类的带参构造函数,2、项目启动后延迟多久执行任务,3、任务间隔多久再次执行)
		timer.schedule(new RankTask(chartLlmService, warningService), 0, 24 * 60 * 60 * 1000);
	}

	/**       
	 * @param sce    
	 */
	@Override
	public void contextDestroyed(ServletContextEvent sce) {

	}

}

3、在web.xml中先配置初始化spring容器的Listener,然后在配置自己的Listener(注,必须先配置sping的Listener

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:application-context.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
  	<listener-class>com.mes.web.controller.llm.Task.RankTaskListener</listener-class>
  </listener>

解释说明:

1、首先要区分Listener的生命周期和spring管理的bean的生命周期。

(1)Listener的生命周期是由servlet容器(例如tomcat)管理的,项目启动时上例中的RankTaskListener是由servlet容器实例化并调用其contextInitialized方法,而servlet容器并不认得@Source注解,因此导致service实例注入失败。

(2)而spring容器中的bean的生命周期是由spring容器管理的。

2、这就需要用到spring为我们提供的WebApplicationContextUtils工具类,该工具类的作用是获取到spring容器的引用,进而获取到我们需要的bean实例。

如:ChartLlmService chartLlmService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(ChartLlmService.class);

3、把service的引用作为参数传给RankTask(),就可以用这个service进行调用了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值