最近在项目中需要用到定时任务来处理一些数据,但是在编写完代码之后(此时逻辑代码写在UserService中的),调试运行时发现报错空指针。此时定时任务类的代码如下:

package ren.misaka.service.scheduler;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import ren.misaka.service.user.UserService;

import java.time.LocalDateTime;

@Service
@RequiredArgsConstructor
@Slf4j
public class ScheduledTaskService {


    private final UserService userService;

    @Scheduled(cron = "0 0/5 * * * ?")
    public void removeExpiredSession() {
        // 输出开始日志
        log.info("开始清理过期session:"+ LocalDateTime.now());
        // 清理过期session
        userService.removeExpiredSession();
        // 输出结束日志
        log.info("清理过期session结束:"+ LocalDateTime.now());
    }
}

而且诡异的是,报错并非是 UserService 空指针,而是清理代码中用到的 RedisCache 空指针了。打了断点一看,发现 UserService 注入的所有类都是空指针。因为我采用了分模块编程,一开始以为是包扫描的问题,指定了扫描目录仍然无果。同时我发现 Controller 也是采用了同样的注入方法,却不会出现这种诡异的注入问题,又把这个类丢去了 Controller 模块,也还是不行。那只能是 SpringBoot 本身的注入问题了。

经过一番查找之后,我找到了一种说法:@Scheduled 注解的优先级较高,导致 UserService 在还未完成注入时,定时任务类就已经初始化了。

那样的话解决方法就很简单了,只需要把逻辑代码搬过来直接在定时任务类里注入 RedisCache 即可。