在Quartz的定时方法里引用@Autowired注入Bean,会报空指针错误
解决办法:
第一种方法:(推荐,简单,亲测可行)
使用@Resource(name="指定要注入的Bean"),代替@Autowired即可,指定了要注入的Bean名字,就能找到该Bean,就不会空指针了。
@Resource(name = "deviceStateProducerService")
private DeviceStateProducerService deviceStateProducerService;
示例代码:
看下面红色字体部分
代码
@Service("microDeviceStateService") public class MicroDeviceStateServiceImpl implements MicroDeviceStateService { @Resource(name = "deviceStateProducerService") private DeviceStateProducerService deviceStateProducerService; @Scheduled(cron="0/10 * * * * * ?") @Lazy(false) public void pingDeviceState() { boolean isSuccess = PingUtils.ping("127.0.0.1", 4, 1000); MicroDeviceState microDeviceState = new MicroDeviceState(); if(!isSuccess) { logger.debug("连接设备状态失败!"); microDeviceState.setDeviceState("1"); }else { microDeviceState.setDeviceState("0"); } microDeviceState.setDeviceFlag("0"); microDeviceState.setIp("127.0.0.1"); DeviceStateBase deviceStateBase = new DeviceStateBase(); BeanUtils.copyProperties(microDeviceState, deviceStateBase); deviceStateProducerService.deviceStateSender(deviceStateBase); } }
有的定时器不生效,在类上加注解@EnableScheduling(spring自带的定时任务功能)
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd" default-lazy-init="true"> <task:scheduler id="scheduler" pool-size="10" /> <task:executor id="executor" keep-alive="3600" pool-size="100-200" queue-capacity="500" rejection-policy="CALLER_RUNS" /> <task:annotation-driven executor="executor" scheduler="scheduler" /> <!-- 注解配置定时器 --> <context:annotation-config /> <!-- spring扫描注解的配置(要扫描的包,即定时器所在包) --> <context:component-scan base-package="com.zit.adapter.camera.CameraListener" /> </beans>
第二种方法:(也可行,不推荐)
使用Spring原生获取Bean的方法 取代 @Autowired注入,同时,不要与定时方法在同一个类
示例代码:
注解方式写了一个定时方法,方法里需要引用Dao层,插入数据库,
直接@Autowired会报空指针异常,做出如下红色字体改动
public class FTPUtil{ // @Autowired // MicroCameraPassRecordDao microCameraPassRecordDao; private static MicroCameraPassRecordDao microCameraPassRecordDao = null; 使用Spring获取注入bean static { microCameraPassRecordDao = (MicroCameraPassRecordDao) SpringContextUtils.getApplicationContext().getBean("microCameraPassRecordDao"); } /** * 定时从FTP下载图片到本地,在这个方法里调用别的Dao层的方法 */ @Scheduled(cron="0/20 * * * * * ?") @Lazy(false) public synchronized void service() { FTPUtil ftpUtil = new FTPUtil(); boolean isConnect = ftpUtil.connectServer(); //从FTP下载到工程file下 boolean flag = ftpUtil.download(getFtpPath()); //引用注入Bean,插入数据库 MicroCameraPassRecord cameraRecord = new MicroCameraPassRecord(); cameraRecord.setCameraId(deviceID); cameraRecord.setAddTime(System.currentTimeMillis()); microCameraPassRecordDao.insert(cameraRecord); } }
getBean(引用类名,开头字母小写)
SpringContextUtils
Spring获取Bean的工具类:
package com.zit.util; import java.util.Map; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Service; @SuppressWarnings({ "rawtypes", "unchecked" }) @Service("springContextUtils") public class SpringContextUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext arg0) throws BeansException { applicationContext = arg0; } /** * 获取applicationContext对象 * @return */ public static ApplicationContext getApplicationContext(){ return applicationContext; } /** * 根据bean的id来查找对象 * @param id * @return */ public static Object getBeanById(String id){ return applicationContext.getBean(id); } /** * 根据bean的class来查找对象 * @param c * @return */ public static Object getBeanByClass(Class c){ return applicationContext.getBean(c); } /** * 根据bean的class来查找所有的对象(包括子类) * @param c * @return */ public static Map getBeansByClass(Class c){ return applicationContext.getBeansOfType(c); } }