最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關于@Autowired注入依賴失敗的問題及解決

 更新時間:2022年08月18日 14:48:36   作者:夜雨落花  
這篇文章主要介紹了關于@Autowired注入依賴失敗的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

@Autowired注入依賴失敗的問題

1、現(xiàn)象描述

在Spring Boot項目中使用@Autowired注解,程序啟動時發(fā)現(xiàn)服務啟動失敗,提示:

Description:
 
Field metrics in com.be.fallback.servlet.FallbackServlet required a bean of type 'com.be.fallback.metrics.FallbackMetrics' that could not be found.
 
The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)
 
 
Action:
 
Consider defining a bean of type 'com.be.fallback.metrics.FallbackMetrics' in your configuration.

2、問題分析

這里的錯誤原因很好分析。結合報錯信息及代碼,報錯處的代碼為FallbackMetrics注解了@Autowired進行依賴注入,但是沒有找到可以被用來注入的實例。即Spring Boot獲取FallbackMetrics的實例失敗。

3、解決方案

根據分析,需要檢查可能導致Spring Boot依賴注入失敗的因素。

1.檢查掃描路徑。

掃描路徑是由@ComponentScan來指定的,默認為標注類當前包及當前包的子包。

也就是說,標注了@ComponentScan的啟動類放在com.be.fallback包下面,只會掃描com.be.fallback包中的類,以及com.be.fallback.servlet、com.be.fallback.util等子包中的類,對于com.be.service等包中的類是不會掃描的。

  • 注意事項一:很多人沒有使用@ComponentScan,但是使用了@SpringBootApplication。@SpringBootApplication是通過內部封裝@ComponentScan注解來實現(xiàn)實例掃描的,所以使用@SpringBootApplication也是一樣的。
  • 注意事項二:也可以通過為@ComponentScan或@SpringBootApplication注解指定參數(shù)來修改掃描路勁,示例:
// 如果使用@ComponentScan注解:
@ComponentScan(basePackages = "com.be.fallback")
?
// 如果使用@SpringBootApplication注解:
@SpringBootApplication(scanBasePackages = "com.be.fallback")

2.檢查實例注冊。

檢查想要使用@Autowired注解自動注入依賴的類,是否標注了用來注冊給Spring Boot的注解。這些注解包括@Component,@Service,@Repository,@Controller等。

3.其他問題。

如果上述步驟檢查完成,服務啟動又沒有產生其他異常,這時候基本上已經排查代碼的問題。這時候需要檢查依賴、開發(fā)環(huán)境等是否有問題。檢查依賴需要了解自己需要哪些依賴,看是否配置齊全;檢查開發(fā)環(huán)境,可以通過將代碼拷貝到其他機器上執(zhí)行來判斷。

@Autowired依賴注入為啥不推薦了

這幾天更新升級了一下java編碼神器IDEA,升級完進行日常開發(fā),可能是以前用的IDEA版本比較老舊,升級之后發(fā)現(xiàn)之前的日常寫法有了個warning提醒。來看圖:

warning1

如上圖,這就奇怪了,我們經常寫的業(yè)務層就是service接口層和對應的實現(xiàn)類層進行屬性注入的時候都是采用注解進行注入的。這也是springIOC給提供的比較方便的地方。我使用IDEA提供的自動修復提示修復了之后變成采用構造函數(shù)的形式進行注入了。

warning2

但是多年面向Spring開發(fā)的經驗告訴我,使用@Autowired注解進行依賴注入,肯定是沒有問題的。但是我的代碼潔癖不允許我這么不明不白的留一個警告在這里。所以,帶著我的潔癖,和我的好奇心,我開始研究起了這個警告。

警告內容

warning3

我們簡單翻譯一下自動提示的是啥意思:

不建議直接在字段上進行依賴注入。

Spring 開發(fā)團隊建議:在Java Bean中永遠使用構造方法進行依賴注入。對于必須的依賴,永遠使用斷言來確認。

我們說明上面的問題之前先回顧幾個spring相關的問題:

依賴注入的方式

Spring 有三種依賴注入的方式

1.基于屬性的注入

這種注入方式就是在bean的變量上使用注解進行依賴注入。本質上是通過反射的方式直接注入到field。這是我平常開發(fā)中看的最多也是最熟悉的一種方式。

@Autowired
PushTaskService pushTaskService;

2.基于setter方法的注入

通過對應變量的setXXX()方法以及在方法上面使用注解,來完成依賴注入。比如:

private static TaskGroupTemplateRepository taskGroupTemplateRepository;
private static TaskGroupService taskGroupService;

@Autowired
public void setTaskGroupTemplateRepository(TaskGroupTemplateRepository taskGroupTemplateRepository,TaskGroupService taskGroupService){
    ExcelListener2.taskGroupTemplateRepository = taskGroupTemplateRepository;
    ExcelListener2.taskGroupService = taskGroupService;
}

說明:在 Spring 4.5 及更高的版本中,setXXX 上面的 @Autowired 注解是可以不寫的。

3.基于構造方法的注入

將各個必需的依賴全部放在帶有注解構造方法的參數(shù)中,并在構造方法中完成對應變量的初始化,這種方式,就是基于構造方法的注入。比如:

@Autowired
public ExcelListener(@Qualifier("taskGroupService") TaskGroupService taskGroupService) {
    this.taskGroupService = taskGroupService;
}

@Autowired是干啥的

我們一般開發(fā)需要注入屬性的時候都會使用的這個注解@Autowired,跟這個注解類似的還有2個,@Resource, @Inject。Spring 支持使用@Autowired, @Resource, @Inject 三個注解進行依賴注入。我們先看一下有啥區(qū)別:

@Autowired為Spring框架提供的注解,可以理解是Spring的親兒子。這里先給出一個示例代碼

public interface IndexService {

    void sayHello();
}

@Service
public class IndexServiceImpl implements IndexService {

    @Override
    public void sayHello() {
        System.out.println("hello, this is IndexServiceImpl");
    }

}

@Service
public class IndexServiceImpl2 implements IndexService {

    @Override
    public void sayHello() {
        System.out.println("hello, this is IndexServiceImpl2");
    }

}

測試方法

@SpringBootTest
public class Stest {

    @Autowired
    // @Qualifier("indexServiceImpl2")
    IndexService indexService;

    @Test
    void gooo() {
        Assertions.assertNotNull(indexService);
        indexService.sayHello();
    }
}

按照type在上下文中查找匹配,查找type為IndexService的bean

  • 如果有多個bean,則按照name進行匹配

如果有@Qualifier注解,則按照@Qualifier指定的name進行匹配,查找name為indexServiceImpl2的bean

如果沒有,則按照變量名進行匹配。查找name為indexService的bean

  • 匹配不到,則報錯。(@Autowired(required=false),如果設置required為false(默認為true),則注入失敗時不會拋出異常)

@Inject是干啥的

在Spring 的環(huán)境下,@Inject和@Autowired 是相同的,因為它們的依賴注入都是使用AutowiredAnnotationBeanPostProcessor這個后置處理器來處理的。

這兩個的區(qū)別,首先@Inject是Java EE包里的,在SE環(huán)境需要單獨引入。另一個區(qū)別在于@Autowired可以設置required=false而@Inject并沒有這個屬性。也有的說@Inject是spring的干兒子。

@Resource是干啥的

@Resource是JSR-250定義的注解。Spring 在 CommonAnnotationBeanPostProcessor實現(xiàn)了對JSR-250的注解的處理,其中就包括@Resource。

這個@Resource有2個屬性name和type。在spring中name屬性定義為bean的名字,type這是bean的類型。

如果屬性上加@Resource注解那么他的注入流程是:

  • 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常。
  • 如果指定了name,則從上下文中查找名稱匹配的bean進行裝配,找不到則拋出異常。
  • 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或是找到多個,都會拋出異常。
  • 如果既沒有指定name,又沒有指定type,則默認按照byName方式進行裝配;如果沒有匹配,按照byType進行裝配。

上面的內容都了解了之后我們接下來看為啥IDEA會有個warning提醒。IDEA 提示 Field injection is not recommended。warning提醒的注入方式就是第一種使用屬性注解的方式進行注入。

屬性注入優(yōu)點

代碼看起來很簡單,通俗易懂。你的類可以專注于業(yè)務而不被依賴注入所污染。你只需要把@Autowired扔到變量之上就好了方便開發(fā)人員進行代碼的編寫。

屬性注入可能出現(xiàn)的問題

  • 問題1

基于 field 的注入,雖然不是絕對禁止使用,但是它可能會帶來一些隱含的問題。來我們舉個例子:

@Autowired
private Person person;

private String company;

public UserServiceImpl(){
    this.company = person.getCompany();
}

初看起來好像沒有什么問題,Person 類會被作為一個依賴被注入到當前類中,同時這個類的 company 屬性將在初始化時通過person.getCompany() 方法來獲得值。我們嘗試運行一下就會發(fā)現(xiàn)報錯了。其實類似這個問題有人在stackoverflow上提問過,點我跳轉。

Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [...]: Constructor threw exception; nested exception is java.lang.NullPointerException

在執(zhí)行this.company = person.getCompany();這段代碼的時候報了空指針。

出現(xiàn)這個問題的原因是,Java 在初始化一個類時,是按照靜態(tài)變量或靜態(tài)語句塊 –> 實例變量或初始化語句塊 –> 構造方法 -> @Autowired 的順序。所以在執(zhí)行這個類的構造方法時,person 對象尚未被注入,它的值還是 null。

  • 問題2

使用這種基于 field 注入的方式,添加依賴是很簡單的,就算你的類中有十幾個依賴你可能都覺得沒有什么問題,如果你一個類注入非常多的其它的對象,擁有太多的依賴通常意味著你的類要承擔更多的責任,明顯違背了單一職責原則。順便我看了一下我們現(xiàn)在的業(yè)務代碼這個問題在我們的項目代碼中真的很常見。

  • 問題3

這種注入形式就會造成你的類不能繞過反射(例如單元測試的時候)進行實例化,必須通過依賴容器才能實例化。也就是類和依賴容器強耦合,不能在容器外使用。

spring建議

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies.

其實大概的意思就是2句話

  • 強制依賴就用構造器方式
  • 可選、可變的依賴就用setter注入

spring對采用構造方法注入的說明

Spring 團隊提倡使用基于構造方法的注入,因為這樣一方面可以將依賴注入到一個不可變的變量中 (注:final 修飾的變量),另一方面也可以保證這些變量的值不會是 null。此外,經過構造方法完成依賴注入的組件 (注:比如各個 service),在被調用時可以保證它們都完全準備好了。與此同時,從代碼質量的角度來看,一個巨大的構造方法通常代表著出現(xiàn)了代碼結構問題,這個類可能承擔了過多的責任。

spring對采用setter方法注入的說明

基于 setter 的注入,則只應該被用于注入非必需的依賴,同時在類中應該對這個依賴提供一個合理的默認值。如果使用 setter 注入必需的依賴,那么將會有過多的 null 檢查充斥在代碼中。使用 setter 注入的一個優(yōu)點是,這個依賴可以很方便的被改變或者重新注入。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • RestTemplate如何添加請求頭headers和請求體body

    RestTemplate如何添加請求頭headers和請求體body

    這篇文章主要介紹了RestTemplate如何添加請求頭headers和請求體body問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • JDBC連接數(shù)據庫步驟及基本操作示例詳解

    JDBC連接數(shù)據庫步驟及基本操作示例詳解

    這篇文章主要為大家介紹了JDBC連接數(shù)據庫步驟及基本操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • SpringBoot接口防抖(防重復提交)的實現(xiàn)方法

    SpringBoot接口防抖(防重復提交)的實現(xiàn)方法

    SpringBoot接口防抖主要通過前端和后端兩種方式實現(xiàn),前端通過JavaScript控制用戶操作,后端通過攔截器、過濾器等機制控制請求頻率,文中介紹的非常詳細,感興趣的可以了解一下
    2024-11-11
  • 淺談Java響應式系統(tǒng)

    淺談Java響應式系統(tǒng)

    第一次聽到reactive這個詞還是在幾年前,偶然了解到了Rxjava這個項目,仿佛為我打開了一扇新的大門,Rxjava是ReactiveX的java實現(xiàn),ReactiveX家族除了Rxjava還有RxJS, Rx.NET,RxScala等等。
    2021-06-06
  • 關于mybatis一對一查詢一對多查詢遇到的問題

    關于mybatis一對一查詢一對多查詢遇到的問題

    這篇文章主要介紹了關于mybatis一對一查詢,一對多查詢遇到的錯誤,接下來是對文章進行操作,要求查詢全部文章,并關聯(lián)查詢作者,文章標簽,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2022-05-05
  • 詳解SpringBoot如何刪除引用jar包中的無用bean

    詳解SpringBoot如何刪除引用jar包中的無用bean

    為了趕速度和直接將之前多模塊的maven項目中的部分模塊,直接以jar包的形式引入到新項目中了,雖然省去了不少開發(fā)時間,導致項目臃腫,啟動很慢。本文將用@ComponentScan注解去實現(xiàn)讓項目只加載自己需要的bean,需要的可以參考一下
    2022-06-06
  • 深入淺析Mybatis與Hibernate的區(qū)別與用途

    深入淺析Mybatis與Hibernate的區(qū)別與用途

    這篇文章主要介紹了Mybatis與Hibernate的區(qū)別與用途的相關資料,需要的朋友可以參考下
    2017-10-10
  • java實現(xiàn)統(tǒng)計字符串中字符及子字符串個數(shù)的方法示例

    java實現(xiàn)統(tǒng)計字符串中字符及子字符串個數(shù)的方法示例

    這篇文章主要介紹了java實現(xiàn)統(tǒng)計字符串中字符及子字符串個數(shù)的方法,涉及java針對字符串的遍歷、判斷及運算相關操作技巧,需要的朋友可以參考下
    2017-01-01
  • mybatis如何使用注解實現(xiàn)一對多關聯(lián)查詢

    mybatis如何使用注解實現(xiàn)一對多關聯(lián)查詢

    這篇文章主要介紹了mybatis如何使用注解實現(xiàn)一對多關聯(lián)查詢的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java多線程死鎖示例

    Java多線程死鎖示例

    這篇文章主要介紹了Java多線程死鎖,結合實例形式分析了Java多線程出現(xiàn)死鎖的相關原因與操作注意事項,需要的朋友可以參考下
    2018-08-08

最新評論

庐江县| 乌鲁木齐县| 仪陇县| 潍坊市| 三门峡市| 大姚县| 桃源县| 浦城县| 清徐县| 怀化市| 宜阳县| 扎囊县| 依兰县| 花垣县| 科尔| 武宣县| 安康市| 高平市| 萝北县| 龙游县| 云南省| 陕西省| 隆昌县| 冷水江市| 娄底市| 鄄城县| 泰宁县| 布拖县| 垫江县| 庆元县| 昌图县| 太原市| 囊谦县| 盐亭县| 大宁县| 安新县| 永嘉县| 岐山县| 安康市| 同德县| 东乡县|