SpringBoot创建ScheduledTask提示需注册Long类bean及后续空指针问题
问题根源
第一个报错(找不到Long类型Bean)
你给ScheduledTask类加了@Component注解时,Spring会自动扫描实例化该类,但你的类只有带Long userId和Timer time两个参数的构造函数,Spring容器中没有对应类型的Bean可以注入到构造参数中,所以抛出找不到java.lang.Long类型Bean的错误。
第二个空指针报错
你手动用new ScheduledTask(1L, new Timer())创建实例时,该对象不归Spring容器管理,Spring不会自动注入你加了@Autowired注解的UserDao,所以userDao是null值,调用userDao.findById时就会触发空指针异常。
解决方案
推荐方案:调整构造函数,通过@Bean方法参数注入依赖
你可以把UserDao也加到构造函数参数中,@Bean方法的参数会被Spring自动注入对应类型的Bean,不需要依赖@Autowired:
- 调整
ScheduledTask的构造函数:
public class ScheduledTask extends TimerTask { private UserDao userDao; private Long userId; private Timer time; // 把UserDao放到构造参数中,去掉@Autowired注解 public ScheduledTask(UserDao userDao, Long userId, Timer time) { this.userDao = userDao; this.userId = userId; this.time = time; } @Override public void run() { Optional<User> userOptional = userDao.findById(userId); if (!userOptional.isPresent()) { time.cancel(); return; } User user = userOptional.get(); BigDecimal globalBalance = user.getGlobalBalance(); user.setGlobalBalance(globalBalance.subtract(Constantes.RELIVRY_COMPANY_FEE)); // 补充:修改完实体属性后需要调用save方法持久化到数据库,否则修改不会生效 userDao.save(user); } }
- 调整
Application中的@Bean定义:
@Bean ScheduledTask scheduledTask(UserDao userDao) { return new ScheduledTask(userDao, 1L, new Timer()); }
额外优化建议
如果你的定时任务没有特殊的动态创建需求,直接使用Spring自带的@Scheduled注解会更简单,不需要手动维护Timer和TimerTask实例,也不需要手动处理依赖注入问题。
内容的提问来源于stack exchange,提问作者Ulyses Evans
相关产品推荐
相关产品推荐

