Spring 注解無效 空指針異常


 

對於Java開發,現在Spring已成為一種生態,使用Spring成為一種享受,Spring的使用讓開發變得更加便捷。

而Spring好用歸好用,若不清楚里面的工作原理,使用的時候難免會踩到一些坑。

 

問題描述

在這里就說一下 注解的使用 ,相信有不少人遇到下面類似的問題:

  “  @Autowired 注入為空 ”

  “ @Resource 注入為空 ”

  “ @PostConstruct 注解無效 ” 

   。。。。。。

這些問題幾乎都是在 非Controller層、非Service層 才會遇到的

不知道你們遇到這些問題的時候,有沒有想過為什么那些注解在 Controller、Service 里面才有效?

 

原理解析

  其實這個得說到Spring的 IOC容器 對 Bean 的管理 。

  在 Spring里面,能夠通過注解獲取到的 Bean 都是由 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注解的問題,到這里就說完了。至於哪個方法更好,就要根據實際情況自己判斷了。

 

 

共同學習,共同進步,若有補充,歡迎指出,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM