springboot集成elastic-job时@Autowired注入service和dao都为空

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了。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值