1、问题根源
springboot集成elastic-job时@Autowired注入service和dao都为空,总结原因是因为定时任务实例对象是new出来的,而不是spring容器管理的,所以@Autowired 的服务都是null。那么将实例对象放入spring容器里面不就解决问题了吗。
2、问题再现
新建elastic-job对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public 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定时任务配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52/** * 定时任务动态配置 * * @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(); }
定时任务初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22Object 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注解即可
1
2
3@Component // 将该类放入到spring容器去管理 public class MySimpleJob implements SimpleJob {
获取spring容器里的bean实例:新建对象SpringContextUtils实现ApplicationContextAware获取spring容器上下文对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56@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)方法初始化定时任务。
1
2
3
4
5SimpleJob 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都为空内容请搜索靠谱客的其他文章。
发表评论 取消回复