本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>
前言
- spring框架中最大的特点是接管了java对象的生命周期。改变了我们以往的构建对象的方式。
- 以前我们通过new构建对象。而在spring中我们通过
Autowired
等方式获取bean
。这种方式的好处是不会开辟不必要的内存
问题描述
- 正常情况通过注入响应的类,spring就会帮我们找到对应的bean。 从而我们能够进行业务操作。
@RestController
@RequestMapping(value = "/init")
public class InitController {
private Map<String, Object> resultMap = new HashMap<>();
@Autowired
TestService testService;
public InitController() {
HashMap<String, Object> paramMap = new HashMap<>();
resultMap = testService.getTable(paramMap);
}
}
问题分析
- 上述的代码乍一看是没有问题的。因为我们的
TestService
是一个正规的service类。在程序启动是在spring构建InitController
的时候就会通过TestService
调用方法获取数据进而存储起来。 - 但是结果却是冷库的。结果显示一大堆的报错。
- 根据堆栈报错信息我们可以看到就是我们
TestService
导致空指针异常的。
- 这是为什么呢?这个我们就需要了解spring构建bean的过程了。在spring构建bean的时候通过三级缓存实现他的构建。这里我们不进行深入解析了。
- 我们要知道spring是先通过new构建一个对象出来此时是一个半成品的bean 。 此时的属性都是默认值。
- 然后在根据spring中的配置完成对这个半成品bean的属性注入
- 所以当
InitController
调用构造的时候不管TestService
有没有准备好都不会注入的。因为此时只是new InitController 。而你在构造器中使用了TestService
所以或抛出空指针异常。
总结
- 关于spring注入的问题我们需要了解bean的生命周期才能知道什么时候可以用、什么时候不可以用。
- spring的一级缓存就是完成半成品属性注入。二级缓存是为了解决循环依赖的问题。而三级缓存是为了解决aop切面的问题
- 后续我们在慢慢展开spring的三级缓存的故事
加油、努力