接到一个问题,说服务启动后偶尔会有空指针的问题。偶现。
背景
项目是 SpringBoot 项目,
按报错,是 service 注入为空,然后在执行时就空指针了。
@Service("xxxService")
public class xxxService {
@Autowired
AService aService;
public void exec(){
aService.run();//这里抛了空指针
}
}
问题表象
偶现的空指针,在服务启动后,有时ok,有时空指针。
问题排查
首先想到的是启动有异常了。Spring Bean 初始化失败了。
登上服务器,启动异常的情况下,看了下启动日志。没有异常。
但是很明显的看到另一个问题。
服务启动时。 Spring Bean 执行了两次实例化 。
问题一下子就明了了。
问题
查看了 main 方法。
public class SpringMain{
public static void main(String[] args){
//.....略过中间逻辑
application.run();
//......略过中间逻辑
application.run();
}
}
明显程序 run 了两次。bean 实例化了两次。
那么为什么 Spring 实例化第二次,就不再初始化 bean 了呢??第二次实例化的 bean 就是个 null 了呢?
原因
这就是 Spring 初始化的流程得了解 。
这里 run 了两次,但 run 的是同一个 Spring 容器,同一个 Spring 容器内会去加载 Bean。
但会判断下 Bean 是否已经初始化了 。 如果已经初始化了,就不再初始化了。
解决
去掉一个 run()
总结
新手们还是要多解一些原理。写代码会写,但定位问题也很重要,
这么明显的执行了两次实例化竟然看不见。。。