欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

為什么Spring和IDEA都不推薦使用 @Autowired 注解

 更新時(shí)間:2022年04月02日 15:04:13   作者:時(shí)間靜止不是簡(jiǎn)史  
本文主要介紹了為什么Spring和IDEA都不推薦使用 @Autowired 注解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

請(qǐng)看下面幾個(gè)問(wèn)題

  • Spring為什么不推薦使用@Autowired 注解?
  • 為什么推薦使用@Resource 代替 @Autowired 注解?
  • 如何快速使用構(gòu)造注入代替 @Autowired ?
  • @Autowired, @Qualifier, @Resource, 三者有何區(qū)別?

下面, 我們帶著以上問(wèn)題去梳理和學(xué)習(xí), 體會(huì)知識(shí)之間的關(guān)聯(lián)性

Spring為什么不推薦使用@Autowired 注解

背景

做開(kāi)發(fā)的同學(xué)可能都會(huì)發(fā)現(xiàn), idea 在我們經(jīng)常使用的@Autowired 注解上添加了警告
警告內(nèi)容是: Field injection is not recommended, 譯為: 不推薦使用屬性注入

在這里插入圖片描述

我們點(diǎn)擊右側(cè)三個(gè)小點(diǎn)查看描述, 可以看到信息如下圖

在這里插入圖片描述

原因詳情描述: Inspection info: Spring Team recommends: "Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies".
譯為: Spring 團(tuán)隊(duì)建議: 始終在您的 bean 中使用基于構(gòu)造函數(shù)的依賴(lài)注入。始終對(duì)強(qiáng)制依賴(lài)項(xiàng)使用斷言

在這里插入圖片描述

原因

為什么 Spring 建議我們?cè)贐ean中使用構(gòu)造注入呢?
想要回答這個(gè)問(wèn)題, 我們需要了解 Spring的依賴(lài)注入(DI)方式
Spring常用的注入方式有: 簡(jiǎn)單類(lèi)型注入, 集合類(lèi)型注入, 域?qū)傩宰詣?dòng)注入, 自動(dòng)注入的類(lèi)別, 空值注入, 構(gòu)造注入
可以簡(jiǎn)化為: 屬性注入, 構(gòu)造方法注入, set 方法注入

下面, 來(lái)用代碼展示下三種方式注入

屬性注入
可以看到, 我們開(kāi)發(fā)最常用的就是屬性注入

@RestController
public class AppointmentNumberConfigurationController {

    @Autowired
    private AppointmentNumberConfigurationService numberConfigurationService;
}

set 方法注入
set 方法注入也會(huì)用到@Autowired注解,但使用方式與屬性注入有所不同,
屬性注入是用在成員變量上,而set 方法的時(shí)候,是用在成員變量的Setter函數(shù)上。

@RestController
public class AppointmentNumberConfigurationController {


    private AppointmentNumberConfigurationService numberConfigurationService;

    @Autowired
    public void setNumberConfigurationService(AppointmentNumberConfigurationService numberConfigurationService) {
        this.numberConfigurationService = numberConfigurationService;
}

構(gòu)造方法注入
Constructor Injection是構(gòu)造器注入,是我們最為推薦的一種使用方式。
但是, 每次注入都按照這樣的流程去構(gòu)造注入的話(huà), 會(huì)顯得比較麻煩.
至于如何去簡(jiǎn)化這一步驟, 我們可以繼續(xù)往下看.

@RestController
public class AppointmentNumberConfigurationController {

    final AppointmentNumberConfigurationService numberConfigurationService;
    
    public AppointmentNumberConfigurationController(AppointmentNumberConfigurationService numberConfigurationService) {
        this.numberConfigurationService = numberConfigurationService;
    }
    }

三種方式對(duì)比如下

在這里插入圖片描述

使用屬性注入可能會(huì)出現(xiàn)的問(wèn)題

基于屬性注入的方式, 違背單一職責(zé)原則
因?yàn)楝F(xiàn)在的業(yè)務(wù)一般都會(huì)使用很多依賴(lài), 但擁有太多的依賴(lài)通常意味著承擔(dān)更多的責(zé)任,而這顯然違背了單一職責(zé)原則.
并且類(lèi)和依賴(lài)容器強(qiáng)耦合,不能在容器外使用。
基于屬性注入的方式, 容易導(dǎo)致Spring 初始化失敗
因?yàn)楝F(xiàn)在在Spring特別是Spring Boot使用中, 經(jīng)常會(huì)因?yàn)槌跏蓟臅r(shí)候, 由于屬性在被注入前就引用而導(dǎo)致npe(空指針錯(cuò)誤),
進(jìn)而導(dǎo)致容器初始化失敗(類(lèi)似下面代碼塊). Java 在初始化一個(gè)類(lèi)時(shí),
是按照 靜態(tài)變量或靜態(tài)語(yǔ)句塊 –> 實(shí)例變量或初始化語(yǔ)句塊 –> 構(gòu)造方法 -> @Autowired 的順序。
所以在執(zhí)行這個(gè)類(lèi)的構(gòu)造方法時(shí),person 對(duì)象尚未被注入,它的值還是 null。
通過(guò)@Autowired 注入, 又因?yàn)槭?ByType 注入, 因此有可能會(huì)出現(xiàn)兩個(gè)相同的類(lèi)型bean
如下代碼快, 就會(huì)產(chǎn)生兩個(gè)相同的Bean, 進(jìn)而導(dǎo)致Spring 裝配失敗
//2. 基于屬性注入的方式, 容易導(dǎo)致Spring 初始化失敗
@Autowired
private Person person;

private String company;

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


//3. 通過(guò)@Autowired 注入, 又因?yàn)槭?ByType 注入, 因此有可能會(huì)出現(xiàn)兩個(gè)相同的類(lèi)型bean
public interface IUser {
    void say();
}

@Service
public class User1 implements IUser{
    @Override
    public void say() {
    }
}

@Service
public class User2 implements IUser{
    @Override
    public void say() {
    }
}

@Service
public class UserService {

    @Autowired
    private IUser user;
} 

解決

如果一定要使用屬性注入, 可以使用 @Resource 代替 @Autowired 注解
@Resource的作用相當(dāng)于@Autowired,只不過(guò)@Autowired按照byType自動(dòng)注入。
如果我們想使用按照名稱(chēng)byName來(lái)裝配,可以結(jié)合@Qualifier注解一起使用。

如果可能的話(huà), 盡量使用構(gòu)造注入
Lombok提供了一個(gè)注解@RequiredArgsConstructor, 可以方便我們快速進(jìn)行構(gòu)造注入, 例如:

@RestController
@RequiredArgsConstructor
public class AppointmentNumberConfigurationController {
    
    final AppointmentNumberConfigurationService numberConfigurationService;
    }

同時(shí)需要注意:

使用@RequiredArgsConstructor注解需要導(dǎo)入Lombok 包 或者安裝lombok 插件

  <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.16</version>
  </dependency>

必須聲明的變量為final

根據(jù)構(gòu)造器注入的,相當(dāng)于當(dāng)容器調(diào)用帶有一組參數(shù)的類(lèi)構(gòu)造函數(shù)時(shí),基于構(gòu)造函數(shù)的 DI 就完成了,
其中每個(gè)參數(shù)代表一個(gè)對(duì)其他類(lèi)的依賴(lài)?;跇?gòu)造方法為屬性賦值,容器通過(guò)調(diào)用類(lèi)的構(gòu)造方法將其進(jìn)行依賴(lài)注入

思考

為什么推薦使用@Resource,不推薦使用@Autowired

通過(guò)對(duì)問(wèn)題1 的梳理, 我們可以知道.
因?yàn)?code>@Autowired 注解在Bean 注入的時(shí)候是基于ByType, 因此會(huì)由于注入兩個(gè)相同類(lèi)型的Bean導(dǎo)致裝配失敗

@Resource的作用相當(dāng)于@Autowired,只不過(guò)@Autowired按照byType自動(dòng)注入。
如果我們想使用按照名稱(chēng)byName來(lái)裝配,可以結(jié)合@Qualifier注解一起使用。

@Resource裝配順序:
①如果同時(shí)指定了name和type,則從Spring上下文中找到唯一匹配的bean進(jìn)行裝配,找不到則拋出異常。
②如果指定了name,則從上下文中查找名稱(chēng)(id)匹配的bean進(jìn)行裝配,找不到則拋出異常。
③如果指定了type,則從上下文中找到類(lèi)似匹配的唯一bean進(jìn)行裝配,找不到或是找到多個(gè),都會(huì)拋出異常。
④如果既沒(méi)有指定name,又沒(méi)有指定type,則自動(dòng)按照byName方式進(jìn)行裝配;如果沒(méi)有匹配,則回退為一個(gè)原始類(lèi)型進(jìn)行匹配,如果匹配則自動(dòng)裝配。

因此, 如果一定要使用屬性注入, 可以使用 @Resource 代替 @Autowired 注解

@Autowired, @Qualifier, @Resource, 三者有何區(qū)別

  • @Autowired: 通過(guò)byType 方式進(jìn)行裝配, 找不到或是找到多個(gè),都會(huì)拋出異常。
  • @Qualifier: 如果想讓@Autowired 注入的Bean進(jìn)行 byName裝配, 可以使用 @Qualifier 進(jìn)行指定
  • @Resource :作用相當(dāng)于@Autowired,只不過(guò) @Resource 默認(rèn)按照byName方式裝配, 如果沒(méi)有匹配, 則退回到 byType 方式進(jìn)行裝配

參考文檔

為什么IDEA不推薦你使用@Autowired?

@Autowired和@Resource的區(qū)別是什么?

到此這篇關(guān)于為什么Spring和IDEA都不推薦使用 @Autowired 注解的文章就介紹到這了,更多相關(guān)Spring IDEA @Autowired 注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論