天天看點

學習Spring,@Autowired的這幾個易錯點你一定要知道!

作者:馬士兵教育CTO

前言

  1. 你是否懂得@Autowired注解在使用上的細節?
  2. 你是否在解決因@Autowired産生的異常而無處下手?
  3. 你是否了解@Autowired的基本原理?

我們在做項目的過程中,随着項目規模的增大、第三方服務的引入,項目中類與類之間的依賴關系錯綜複雜,而@Autowired作為在依賴注入中最常使用到的注解,若沒有一定的知識儲備,遇到問題就直接百度搜報錯資訊的話,很大程度會造成一杯茶一包煙,一個bug搞一天。

本篇文章我将從以上三個問題出發講解@Autowired使用中容易出錯的地方。

一.@Autowired的使用細節

1.依賴注入:@Autowired它可以對類成員變量、方法及構造函數三處地方進行标注。标注在函數上時,@Autowired會自動識别函數上的參數,接着從Spring容器中找到對應的Bean進行依賴注入,同時也可以搭配@Qualifier解決歧義問題。

學習Spring,@Autowired的這幾個易錯點你一定要知道!

2.多個比對的Bean的處理:@Autowired預設按照byType(屬性類型)裝配方式,如果遇到多個比對的Bean或者需要根據名稱進行裝配,可以結合@Qualifier注解來指定要注入的Bean名稱。

3.@Autowired的可選性: 使用@Autowired(required = false)可以将依賴标記為可選的。如果找不到比對的Bean,将不會抛出異常,但需要注意處理依賴缺失的情況以防止NPE異常。

4.@Autowired标注的字段的引用:在使用了@Autowired注解的Java中類的初始化順序為

靜态變量->靜态初始化塊->變量初始化->初始化塊->構造器->@Autowired标注的變量指派

也就是說标注了@Autowired注解的變量要等到類完全加載完才會将相應的bean注入。是以不要在構造器中使用被@Autowired注解标注的變量。

學習Spring,@Autowired的這幾個易錯點你一定要知道!

二.@Autowired常見的棘手的異常

以下幾種異常是邊試我們在使用@Autowired注解中經常遇到的。

  1. BeanCreationException:Bean建立失敗

這種問題可能是由于Bean的構造函數抛出異常、初始化失敗等原因引起的。

學習Spring,@Autowired的這幾個易錯點你一定要知道!
  1. UnsatisfiedDependencyException:存在多個比對的Bean
  2. 在我們日常使用Springboot開發中此情況常見于一個service接口有多個實作類,因為@Autowired注解進行依賴注入時是預設按屬性類型的,此時對該service進行依賴注入時,容器中出現多個類型相同bean(因為它有多個實作類),容器不知道為它注入哪個,隻能走抛異常的方式。
學習Spring,@Autowired的這幾個易錯點你一定要知道!

運作結果:

學習Spring,@Autowired的這幾個易錯點你一定要知道!
  1. NoSuchBeanDefinitionException

當Spring容器無法找到與@Autowired注解所需類型比對的Bean時,就會抛出NoSuchBeanDefinitionException異常。

  1. BeanCurrentlyInCreationException:循環依賴問題

使用@Autowired時,如果存在循環依賴(A依賴B,B又依賴A),會導緻BeanCurrentlyInCreationException異常。

學習Spring,@Autowired的這幾個易錯點你一定要知道!

運作結果:

學習Spring,@Autowired的這幾個易錯點你一定要知道!

5.NullPointException:空指針異常

沒錯,NullPointException也是使用Autowired常常碰到的異常。這種異常經常出現在依賴未注入而導緻的。@Autowired的使用細節目錄中提到的1,2,4都有可能導緻。

三.@Autowired底層簡述

在Spring中有着一個後處理器的概念,每一個後處理器都有着解析一種或者多種注解的功能。@Autowired正是由AutowiredAnnotationBeanPostProcessor進行解析的。它的流程分為兩步,第一:找到類中@Autowired标注的的屬性或者函數;第二:到容器去找到對應類型的bean去注入。

這個方法具體在AutowiredAnnotationBeanPostProcessor的258行

學習Spring,@Autowired的這幾個易錯點你一定要知道!

接着我們做個測試,進行debug

這是用到的類,這裡的UserMapper故意沒标注@Mapper注解,模拟出錯情況。

學習Spring,@Autowired的這幾個易錯點你一定要知道!

藍色那一行,底層根據beanName:“userServiceImpl”到緩存中找到類的中繼資料,

學習Spring,@Autowired的這幾個易錯點你一定要知道!

傳回的中繼資料中有userServiceImpl中用@Autowired标注的屬性“userMapper”

學習Spring,@Autowired的這幾個易錯點你一定要知道!

接着進行一個資料校驗(非空判斷)

學習Spring,@Autowired的這幾個易錯點你一定要知道!

最終來到依賴注入階段

學習Spring,@Autowired的這幾個易錯點你一定要知道!

發現容器中并沒有比對的bean(前面故意沒在mapper接口上加mapper注解),執行報異常的操作

學習Spring,@Autowired的這幾個易錯點你一定要知道!

以防上圖看的不清楚

學習Spring,@Autowired的這幾個易錯點你一定要知道!

作者:與驢OO

連結:https://juejin.cn/post/7260763321480790053

來源:稀土掘金

著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。