Spring注解⽆效空指针异常
对于Java开发,现在Spring已成为⼀种⽣态,使⽤Spring成为⼀种享受,Spring的使⽤让开发变得更加便捷。
⽽Spring好⽤归好⽤,若不清楚⾥⾯的⼯作原理,使⽤的时候难免会踩到⼀些坑。
问题描述
在这⾥就说⼀下注解的使⽤,相信有不少⼈遇到下⾯类似的问题:
  “  @Autowired 注⼊为空 ”
  “ @Resource 注⼊为空 ”
  “ @PostConstruct 注解⽆效 ”
  。。。。。。
这些问题⼏乎都是在⾮Controller层、⾮Service层才会遇到的
不知道你们遇到这些问题的时候,有没有想过为什么那些注解在 Controller、Service ⾥⾯才有效?
原理解析
  其实这个得说到Spring的 IOC容器对 Bean 的管理。
  在 Spring⾥⾯,能够通过注解获取到的 Bean 都是由 IOC容器来管理获取的。
spring ioc注解
  在IOC容器启动阶段,IOC 会通过配置⽂件读取、类扫描、注解识别等等⼏个步骤,来进⾏ Bean 的实例化。其中,最关键的是注解识别,⼏乎都是加了指定注解的类才有可能被注册到 IOC容器(⽐如说  @Controller 、 @Service 、 @Component ......  )。同样,也只有加了这些注解后,才能在类内正常使⽤ @Autowired 之类的注解(因为在Bean实例化的时候,@Autowired 之类的注解会初始化Bean⾥⾯的变量)。⽽且 IOC容器⾥⾯的Bean都是单例模式,这也很好理解,如果有多个实例,当使⽤ @Autowired 获取Bean的时候,怎么知道该返回哪个实例呢?
追根溯源
  说到这,理解还不是很透彻的⼩伙伴,可能对前⾯举出的注解问题,还没想明⽩原因所在,“ 我也已经在类前⾯加了 @Component ,可是 @Autowired 的变量还是空指针!这⼜是什么原因? ”  。
先举个例⼦,
  C 类是需要 @Autowired 注⼊的变量,已证明在Controller、Service层都能使⽤注⼊正常;
  B 类是加了 @Component 的,并且使⽤了@Autowired 注⼊标识C类变量;
  A 类是通过 new B().method()  来调⽤ B类逻辑的。
  然后在 B类⼀个⽅法中使⽤C类变量的时候,报了空指针异常!
如果你遇到的情况是这样⼦的,那问题就在于 B类的被调⽤⽅式。虽然加了 @Component 注解,在容器初始化的时候,B类是已经被注册到了 IOC容器的。
  但由于 B类被调⽤的时候,是通过 new 的⽅式获取的,这样就违背了 IOC / DI 原则。所以B类⽆法被IOC容器当成单例去管理,也就是IOC容器发现后会把前⾯注册在IOC的B类实例丢弃删掉,即在IOC容器⾥⾯没有了B类的实例。
那在调⽤ B类⽅法逻辑的时候,其中 @Autowired 注⼊的C类变量就不会⾃动被初始化,你拿到的当然是空指针。
那怎么办?注解使⽤很⽅便,我不想抛弃它,⼜希望在B类中能够发挥它的作⽤。
两个解决⽅法:
⽅法⼀:使⽤静态变量存储C类的实例
  具体描述:在B类中,添加⼀个静态变量,使⽤ @PostConstruct 注解初始化⽅法init() ,在init() ⽅法⾥⾯给静态变量赋值,原本调⽤C类变量的地⽅使⽤静态变量来代替。( @PostConstruct是在IOC启动构造完成后执⾏的,那个时候B类还没被抛出IOC容器)
⽅法⼆:在B类调⽤的地⽅,修改其调⽤的⽅式,不能使⽤ new 来实例化调⽤
有关Spring注解的问题,到这⾥就说完了。⾄于哪个⽅法更好,就要根据实际情况⾃⼰判断了。
共同学习,共同进步,若有补充,欢迎指出,谢谢!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。