概述
1、问题根源
springboot集成elastic-job时@Autowired注入service和dao都为空,总结原因是因为定时任务实例对象是new出来的,而不是spring容器管理的,所以@Autowired 的服务都是null。那么将实例对象放入spring容器里面不就解决问题了吗。
2、问题再现
新建elastic-job对象
public class MySimpleJob implements SimpleJob {
private Logger log = LoggerFactory.getLogger(MySimpleJob.class);
@Autowired
private FtpConfigTbDao ftpConfigTbDao;
@Override
public void execute(ShardingContext shardingContext) {
log.info(String.format("------Thread ID: %s, 任务总片数: %s, " + "当前分片项: %s.当前参数: %s," + "当前任务名称: %s.当前任务参数: %s",
Thread.currentThread().getId(), shardingContext.getShardingTotalCount(),
shardingContext.getShardingItem(), shardingContext.getShardingParameter(), shardingContext.getJobName(),
shardingContext.getJobParameter()));
Map<String, String> paramsFtp = new HashMap<String, String>();
paramsFtp.put("channelType", "JINGDONG");// 渠道
paramsFtp.put("fileFlag", shardingContext.getShardingParameter());// 文件标识为当前参数
FtpConfigTb ftpConfigTb = ftpConfigTbDao.getFtpByChannelTypeAndFileType(paramsFtp);
log.info("查询:{}", ftpConfigTb.toString());
}
}
elastic-job定时任务配置
/**
* 定时任务动态配置
*
* @param simpleJob
* @param jobName
*
任务名称
* @param cron
*
任务启动时钟配置 "0/20 * * * * ?"
* @param shardingTotalCount
*
分片数
* @param shardingItemParameters
*
任务参数 例:0=A,1=B
* @return
*/
public JobScheduler simpleJobScheduler(SimpleJob simpleJob, String jobName, String cron, int shardingTotalCount,
String shardingItemParameters) {
log.info(String.format("任务总片数: %s, " + "参数: %s," + "任务配置: %s", shardingTotalCount, shardingItemParameters,
cron));
return new SpringJobScheduler(simpleJob, regCenter, getLiteJobConfiguration(simpleJob.getClass(), jobName, cron,
shardingTotalCount, shardingItemParameters));
}
/**
*
* @param jobClass
*
实现SimpleJob接口的实例
* @param jobName
*
定时任务名称
* @param cron
*
任务启动时间 格式 "0/20 * * * * ?"
* @param shardingTotalCount
*
分片数
* @param shardingItemParameters
*
任务参数 ,例子:0=A,1=B
* @return
*/
private LiteJobConfiguration getLiteJobConfiguration(Class<? extends SimpleJob> jobClass, String jobName,
String cron, int shardingTotalCount, String shardingItemParameters) {
return LiteJobConfiguration.newBuilder(new SimpleJobConfiguration(
JobCoreConfiguration.newBuilder(jobName, cron, shardingTotalCount)
.shardingItemParameters(shardingItemParameters).jobParameter(shardingItemParameters).build(),
jobClass.getCanonicalName())).overwrite(true).build();
}
定时任务初始化
Object obj = getBean(refClass);
SimpleJob simpleJob = (SimpleJob) obj;
JobScheduler jobScheduler = simpleJobScheduler(simpleJob, jobName, cron, totalCount, itemParam);
jobScheduler.init();
/**
* 获取类实例
*
* @param beanName
* @return
*/
public Object getBean(String beanName) {
Class<?> clas = null;
try {
clas = Class.forName(beanName);
return clas.newInstance();
} catch (Exception e) {
e.printStackTrace();
log.info("获取【{}】类实例错误:{}", beanName, e.getMessage());
}
return null;
}
这么配置的任务是没有问题的,但是@Autowired注入的FtpConfigTbDao是null。
3、解决问题
问题根源就是对象实例是通过clas.newInstance()实例化出来的,没有放入到spring容器里面,@Autowired注解就没有效果了。
那么将任务实例注入成spring的一个bean,该任务就在spring容器里面了,那么问题又来的,如何获取spring容器里的bean呢?且看下方:
将任务注入到spring容器里:添加@Component注解即可
@Component // 将该类放入到spring容器去管理
public class MySimpleJob implements SimpleJob {
获取spring容器里的bean实例:新建对象SpringContextUtils实现ApplicationContextAware获取spring容器上下文对象
@Component
public class SpringContextUtils implements ApplicationContextAware {
/**
* spring容器上下文对象
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
/**
* 获取上下文对象实例
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过bean名称获取实例
*
* 该bean一般添加@Component注解就行了
*
* @param name
*
bean名称
* @return 实例对象
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过类class获取实例
*
* 该bean一般添加@Component注解就行了
*
* @param clazz
* @return 实例对象
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过类name,class获取指定的实例
*
* 该bean一般添加@Component注解就行了
*
* @param name
* @param clazz
* @return 实例对象
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
接下来获取spring容器里的bean实例放入到 simpleJobScheduler(simpleJob, jobName, cron, totalCount, itemParam)方法初始化定时任务。
SimpleJob simpleJob = (SimpleJob) SpringContextUtils.getBean(refClass);
JobScheduler jobScheduler = simpleJobScheduler(simpleJob, jobName, cron, totalCount, itemParam);
jobScheduler.init();
问题解决。这会儿
@Autowired
private FtpConfigTbDao ftpConfigTbDao;
就不是null了。
最后
以上就是务实鸭子为你收集整理的springboot集成elastic-job时@Autowired注入service和dao都为空的全部内容,希望文章能够帮你解决springboot集成elastic-job时@Autowired注入service和dao都为空所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复