前言
- 你是否懂得@Autowired注解在使用上的細節?
- 你是否在解決因@Autowired産生的異常而無處下手?
- 你是否了解@Autowired的基本原理?
我們在做項目的過程中,随着項目規模的增大、第三方服務的引入,項目中類與類之間的依賴關系錯綜複雜,而@Autowired作為在依賴注入中最常使用到的注解,若沒有一定的知識儲備,遇到問題就直接百度搜報錯資訊的話,很大程度會造成一杯茶一包煙,一個bug搞一天。
本篇文章我将從以上三個問題出發講解@Autowired使用中容易出錯的地方。
一.@Autowired的使用細節
1.依賴注入:@Autowired它可以對類成員變量、方法及構造函數三處地方進行标注。标注在函數上時,@Autowired會自動識别函數上的參數,接着從Spring容器中找到對應的Bean進行依賴注入,同時也可以搭配@Qualifier解決歧義問題。
2.多個比對的Bean的處理:@Autowired預設按照byType(屬性類型)裝配方式,如果遇到多個比對的Bean或者需要根據名稱進行裝配,可以結合@Qualifier注解來指定要注入的Bean名稱。
3.@Autowired的可選性: 使用@Autowired(required = false)可以将依賴标記為可選的。如果找不到比對的Bean,将不會抛出異常,但需要注意處理依賴缺失的情況以防止NPE異常。
4.@Autowired标注的字段的引用:在使用了@Autowired注解的Java中類的初始化順序為
靜态變量->靜态初始化塊->變量初始化->初始化塊->構造器->@Autowired标注的變量指派
也就是說标注了@Autowired注解的變量要等到類完全加載完才會将相應的bean注入。是以不要在構造器中使用被@Autowired注解标注的變量。
二.@Autowired常見的棘手的異常
以下幾種異常是邊試我們在使用@Autowired注解中經常遇到的。
- BeanCreationException:Bean建立失敗
這種問題可能是由于Bean的構造函數抛出異常、初始化失敗等原因引起的。
- UnsatisfiedDependencyException:存在多個比對的Bean
- 在我們日常使用Springboot開發中此情況常見于一個service接口有多個實作類,因為@Autowired注解進行依賴注入時是預設按屬性類型的,此時對該service進行依賴注入時,容器中出現多個類型相同bean(因為它有多個實作類),容器不知道為它注入哪個,隻能走抛異常的方式。
運作結果:
- NoSuchBeanDefinitionException
當Spring容器無法找到與@Autowired注解所需類型比對的Bean時,就會抛出NoSuchBeanDefinitionException異常。
- BeanCurrentlyInCreationException:循環依賴問題
使用@Autowired時,如果存在循環依賴(A依賴B,B又依賴A),會導緻BeanCurrentlyInCreationException異常。
運作結果:
5.NullPointException:空指針異常
沒錯,NullPointException也是使用Autowired常常碰到的異常。這種異常經常出現在依賴未注入而導緻的。@Autowired的使用細節目錄中提到的1,2,4都有可能導緻。
三.@Autowired底層簡述
在Spring中有着一個後處理器的概念,每一個後處理器都有着解析一種或者多種注解的功能。@Autowired正是由AutowiredAnnotationBeanPostProcessor進行解析的。它的流程分為兩步,第一:找到類中@Autowired标注的的屬性或者函數;第二:到容器去找到對應類型的bean去注入。
這個方法具體在AutowiredAnnotationBeanPostProcessor的258行
接着我們做個測試,進行debug
這是用到的類,這裡的UserMapper故意沒标注@Mapper注解,模拟出錯情況。
藍色那一行,底層根據beanName:“userServiceImpl”到緩存中找到類的中繼資料,
傳回的中繼資料中有userServiceImpl中用@Autowired标注的屬性“userMapper”
接着進行一個資料校驗(非空判斷)
最終來到依賴注入階段
發現容器中并沒有比對的bean(前面故意沒在mapper接口上加mapper注解),執行報異常的操作
以防上圖看的不清楚
作者:與驢OO
連結:https://juejin.cn/post/7260763321480790053
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。