亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

關(guān)于@Autowired注入依賴失敗的問題及解決

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

@Autowired注入依賴失敗的問題

1、現(xiàn)象描述

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

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、問題分析

這里的錯(cuò)誤原因很好分析。結(jié)合報(bào)錯(cuò)信息及代碼,報(bào)錯(cuò)處的代碼為FallbackMetrics注解了@Autowired進(jìn)行依賴注入,但是沒有找到可以被用來注入的實(shí)例。即Spring Boot獲取FallbackMetrics的實(shí)例失敗。

3、解決方案

根據(jù)分析,需要檢查可能導(dǎo)致Spring Boot依賴注入失敗的因素。

1.檢查掃描路徑。

掃描路徑是由@ComponentScan來指定的,默認(rèn)為標(biāo)注類當(dāng)前包及當(dāng)前包的子包。

也就是說,標(biāo)注了@ComponentScan的啟動(dòng)類放在com.be.fallback包下面,只會(huì)掃描com.be.fallback包中的類,以及com.be.fallback.servlet、com.be.fallback.util等子包中的類,對(duì)于com.be.service等包中的類是不會(huì)掃描的。

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

2.檢查實(shí)例注冊(cè)。

檢查想要使用@Autowired注解自動(dòng)注入依賴的類,是否標(biāo)注了用來注冊(cè)給Spring Boot的注解。這些注解包括@Component,@Service,@Repository,@Controller等。

3.其他問題。

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

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

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

warning1

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

warning2

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

警告內(nèi)容

warning3

我們簡(jiǎn)單翻譯一下自動(dòng)提示的是啥意思:

不建議直接在字段上進(jìn)行依賴注入。

Spring 開發(fā)團(tuán)隊(duì)建議:在Java Bean中永遠(yuǎn)使用構(gòu)造方法進(jìn)行依賴注入。對(duì)于必須的依賴,永遠(yuǎn)使用斷言來確認(rèn)。

我們說明上面的問題之前先回顧幾個(gè)spring相關(guān)的問題:

依賴注入的方式

Spring 有三種依賴注入的方式

1.基于屬性的注入

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

@Autowired
PushTaskService pushTaskService;

2.基于setter方法的注入

通過對(duì)應(yīng)變量的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.基于構(gòu)造方法的注入

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

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

@Autowired是干啥的

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

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

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");
    }

}

測(cè)試方法

@SpringBootTest
public class Stest {

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

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

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

  • 如果有多個(gè)bean,則按照name進(jìn)行匹配

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

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

  • 匹配不到,則報(bào)錯(cuò)。(@Autowired(required=false),如果設(shè)置required為false(默認(rèn)為true),則注入失敗時(shí)不會(huì)拋出異常)

@Inject是干啥的

在Spring 的環(huán)境下,@Inject和@Autowired 是相同的,因?yàn)樗鼈兊囊蕾囎⑷攵际鞘褂肁utowiredAnnotationBeanPostProcessor這個(gè)后置處理器來處理的。

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

@Resource是干啥的

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

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

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

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

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

屬性注入優(yōu)點(diǎn)

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

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

  • 問題1

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

@Autowired
private Person person;

private String company;

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

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

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();這段代碼的時(shí)候報(bào)了空指針。

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

  • 問題2

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

  • 問題3

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

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.

其實(shí)大概的意思就是2句話

  • 強(qiáng)制依賴就用構(gòu)造器方式
  • 可選、可變的依賴就用setter注入

spring對(duì)采用構(gòu)造方法注入的說明

Spring 團(tuán)隊(duì)提倡使用基于構(gòu)造方法的注入,因?yàn)檫@樣一方面可以將依賴注入到一個(gè)不可變的變量中 (注:final 修飾的變量),另一方面也可以保證這些變量的值不會(huì)是 null。此外,經(jīng)過構(gòu)造方法完成依賴注入的組件 (注:比如各個(gè) service),在被調(diào)用時(shí)可以保證它們都完全準(zhǔn)備好了。與此同時(shí),從代碼質(zhì)量的角度來看,一個(gè)巨大的構(gòu)造方法通常代表著出現(xiàn)了代碼結(jié)構(gòu)問題,這個(gè)類可能承擔(dān)了過多的責(zé)任。

spring對(duì)采用setter方法注入的說明

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

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談Java線程池的7大核心參數(shù)

    淺談Java線程池的7大核心參數(shù)

    本篇文章基于正在看這篇文章的你已經(jīng)具備了基本的Java并發(fā)的相關(guān)知識(shí).如果對(duì)于Java并發(fā)編程一無所知的話,請(qǐng)先看看Java并發(fā)編程的一些前導(dǎo)基礎(chǔ)知識(shí),文中有非常詳細(xì)的圖文示例及代碼,,需要的朋友可以參考下
    2021-05-05
  • MAC下如何設(shè)置JDK環(huán)境變量

    MAC下如何設(shè)置JDK環(huán)境變量

    這篇文章主要介紹了MAC下如何設(shè)置JDK環(huán)境變量問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Springboot+Stomp協(xié)議實(shí)現(xiàn)聊天功能

    Springboot+Stomp協(xié)議實(shí)現(xiàn)聊天功能

    本示例實(shí)現(xiàn)一個(gè)功能,前端通過websocket發(fā)送消息給后端服務(wù),后端服務(wù)接收到該消息時(shí),原樣將消息返回給前端,前端技術(shù)棧html+stomp.js,后端SpringBoot,需要的朋友可以參考下
    2024-02-02
  • Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之養(yǎng)老院管理系統(tǒng)的實(shí)現(xiàn)

    Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之養(yǎng)老院管理系統(tǒng)的實(shí)現(xiàn)

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+JSP+Easyui+maven+mysql實(shí)現(xiàn)一個(gè)養(yǎng)老院管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平
    2022-03-03
  • drools規(guī)則動(dòng)態(tài)化實(shí)踐解析

    drools規(guī)則動(dòng)態(tài)化實(shí)踐解析

    這篇文章主要為大家介紹了drools規(guī)則動(dòng)態(tài)化實(shí)踐解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 淺談Java回收對(duì)象的標(biāo)記和對(duì)象的二次標(biāo)記過程

    淺談Java回收對(duì)象的標(biāo)記和對(duì)象的二次標(biāo)記過程

    這篇文章主要介紹了淺談Java回收對(duì)象的標(biāo)記和對(duì)象的二次標(biāo)記過程的相關(guān)內(nèi)容,小編覺得還是挺不錯(cuò)的,這里給大家分享一下,需要的朋友可以參考。
    2017-10-10
  • 淺析java 的 static 關(guān)鍵字用法

    淺析java 的 static 關(guān)鍵字用法

    這篇文章主要介紹了淺析java 的 static 關(guān)鍵字用法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • Java中控制流程語句的深入講解

    Java中控制流程語句的深入講解

    流程控制語句顧名思義就是控制程序走向的語句,其中包括條件語句,分支語句和循環(huán)語句,這篇文章主要給大家介紹了關(guān)于Java中控制流程語句的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10
  • Java Spring的數(shù)據(jù)庫開發(fā)詳解

    Java Spring的數(shù)據(jù)庫開發(fā)詳解

    這篇文章主要介紹了Spring的數(shù)據(jù)庫開發(fā),主要圍繞SpringJDBC和Spring Jdbc Template兩個(gè)技術(shù)來講解,文中有詳細(xì)的代碼示例,需要的小伙伴可以參考一下
    2023-04-04
  • 關(guān)于如何搭建CAS服務(wù)并將CAS項(xiàng)目導(dǎo)入IDEA

    關(guān)于如何搭建CAS服務(wù)并將CAS項(xiàng)目導(dǎo)入IDEA

    這篇文章主要介紹了關(guān)于如何搭建CAS服務(wù)并將CAS項(xiàng)目導(dǎo)入IDEA的問題,文中提供了詳細(xì)的圖文講解,需要的朋友可以參考下,如果有錯(cuò)誤的地方還請(qǐng)指正
    2023-03-03

最新評(píng)論