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

基于spring DI的三種注入方式分析

 更新時(shí)間:2021年07月05日 09:46:26   作者:CrazySnail_x  
這篇文章主要介紹了基于spring DI的三種注入方式分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。

一.前言: IOC(控制反轉(zhuǎn))與DI(依賴注入)

Spring框架對(duì)Java開(kāi)發(fā)的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反轉(zhuǎn))和AOP,平時(shí)使用最多的就是其中的IOC,我們通過(guò)將組件交由Spring的IOC容器管理,將對(duì)象的依賴關(guān)系由Spring控制,避免硬編碼所造成的過(guò)度程序耦合。

在講依賴注入之前,我覺(jué)得有必要了解一下IOC(控制反轉(zhuǎn))與DI(依賴注入)的關(guān)系,在這篇文章中有詳細(xì)的介紹:spring IOC 與 DI。

二.DI的三種常見(jiàn)注入方式

DI的三種常見(jiàn)注入方式為:setter注入、構(gòu)造器注入和基于注解的注入(也叫field注入),下面來(lái)分別講講他們的特點(diǎn)。

2.1 基于注解注入

首先來(lái)看一下它的實(shí)現(xiàn):

@RestController
@RequestMapping("/annotation")
public class AnnotationController {
    @Autowired
    private DiService diService;
 
    @GetMapping("/test001")
    public String test001() {
        return diService.test001("annotation");
    }
}

這種方式應(yīng)該是目前最常見(jiàn)的注入方式了,原因很簡(jiǎn)單:

1、注入方式非常簡(jiǎn)單:加上@Autowired注解,加入要注入的字段,即可完成。

2、使得整體代碼簡(jiǎn)潔明了,看起來(lái)美觀大方。

在介紹注解注入的方式前,先簡(jiǎn)單了解bean的一個(gè)屬性autowire,autowire主要有三個(gè)屬性值:constructor,byName,byType。

  • constructor:通過(guò)構(gòu)造方法進(jìn)行自動(dòng)注入,spring會(huì)匹配與構(gòu)造方法參數(shù)類型一致的bean進(jìn)行注入,如果有一個(gè)多參數(shù)的構(gòu)造方法,一個(gè)只有一個(gè)參數(shù)的構(gòu)造方法,在容器中查找到多個(gè)匹配多參數(shù)構(gòu)造方法的bean,那么spring會(huì)優(yōu)先將bean注入到多參數(shù)的構(gòu)造方法中。
  • byName:被注入bean的id名必須與set方法后半截匹配,并且id名稱的第一個(gè)單詞首字母必須小寫,這一點(diǎn)與手動(dòng)set注入有點(diǎn)不同。
  • byType:查找所有的set方法,將符合符合參數(shù)類型的bean注入。

下面進(jìn)入正題:

注解方式注冊(cè)bean:

在以前的開(kāi)發(fā)中,我們主要使用四種注解注冊(cè)bean,每種注解可以任意使用,只是語(yǔ)義上有所差異:

  1. @Component:可以用于注冊(cè)所有bean
  2. @Repository:主要用于注冊(cè)dao層的bean
  3. @Controller:主要用于注冊(cè)控制層的bean
  4. @Service:主要用于注冊(cè)服務(wù)層的bean

隨著springboot的流行,@Bean注解也逐漸的被我們使用起來(lái)。Spring的@Bean注解用于告訴方法,產(chǎn)生一個(gè)Bean對(duì)象,然后這個(gè)Bean對(duì)象交給Spring管理。產(chǎn)生這個(gè)Bean對(duì)象的方法Spring只會(huì)調(diào)用一次,隨后這個(gè)Spring將會(huì)將這個(gè)Bean對(duì)象放在自己的IOC容器中。

注解方式注入依賴(主要有兩種):

  • @Resource :java的注解,默認(rèn)以byName的方式去匹配與屬性名相同的bean的id,如果沒(méi)有找到就會(huì)以byType的方式查找,如果byType查找到多個(gè)的話,使用@Qualifier注解(spring注解)指定某個(gè)具體名稱的bean。
  • @Autowired :spring注解,默認(rèn)是以byType的方式去匹配類型相同的bean,可以結(jié)合@Qualifier 注解根據(jù)byName方式匹配。

關(guān)于他們的具體用法與區(qū)別,因?yàn)閮?nèi)容比較多,所以寫在另一篇博客中,請(qǐng)見(jiàn):@Autowired 和 @Resource 詳解

2.2 構(gòu)造器注入

老規(guī)矩,先上代碼示例:

@RestController
@RequestMapping("/constructor")
public class ConstructorController {
    private final DiService diService;
    private final String result; 
    public ConstructorController(DiService diService) {
        this.diService = diService;
        this.result = diService.test001("constructor");
    }
 
    @GetMapping("/test001")
    public String test001() {
        return diService.test001(this.result);
    }
}

這里有一個(gè)問(wèn)題,如果只有一個(gè)有參數(shù)的構(gòu)造方法并且參數(shù)類型與注入的bean的類型匹配,那就會(huì)注入到該構(gòu)造方法中。如果有多個(gè)有參數(shù)的構(gòu)造方法并且每個(gè)構(gòu)造方法的參數(shù)列表里面都有要注入的屬性,那userDaoJdbc會(huì)注入到哪里呢?

在Spring4.x版本中推薦的注入方式就是這種,相較于上面的field注入方式而言,就顯得有點(diǎn)難看,特別是當(dāng)注入的依賴很多(5個(gè)以上)的時(shí)候,就會(huì)明顯的發(fā)現(xiàn)代碼顯得很臃腫。對(duì)于從field注入轉(zhuǎn)過(guò)來(lái)+有強(qiáng)迫癥的同學(xué)來(lái)說(shuō),簡(jiǎn)直可以說(shuō)是石樂(lè)志 ,但是為啥spring官方還會(huì)這么推薦呢?

官方文檔里是這么說(shuō)的:

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state.

翻譯一下就是:Spring團(tuán)隊(duì)通常提倡構(gòu)造函數(shù)注入,因?yàn)樗试S將應(yīng)用程序組件實(shí)現(xiàn)為不可變的對(duì)象,并確保所需的依賴不為空。此外,注入構(gòu)造函數(shù)的組件總是以完全初始化的狀態(tài)返回給客戶機(jī)(調(diào)用)代碼。

簡(jiǎn)單解釋一下:

  • 不可變的對(duì)象:其實(shí)說(shuō)的就是final關(guān)鍵字,這里不再多解釋了。
  • 依賴不為空:省去了我們對(duì)其檢查。當(dāng)要實(shí)例化ConstructorController的時(shí)候,由于自己實(shí)現(xiàn)了有參數(shù)的構(gòu)造函數(shù),所以不會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù),那么就需要Spring容器傳入所需要的參數(shù),所以就兩種情況:1、有該類型的參數(shù)->傳入,OK 。2:無(wú)該類型的參數(shù)->報(bào)錯(cuò)。這樣就可以保證不會(huì)為空。
  • 完全初始化的狀態(tài):這個(gè)可以跟上面的依賴不為空結(jié)合起來(lái),向構(gòu)造器傳參之前,要確保注入的內(nèi)容不為空,那么肯定要調(diào)用依賴組件的構(gòu)造方法完成實(shí)例化。而在Java類加載實(shí)例化的過(guò)程中,構(gòu)造方法是最后一步(之前如果有父類先初始化父類,然后自己的成員變量,最后才是構(gòu)造方法,這里不詳細(xì)展開(kāi)。)。所以返回來(lái)的都是初始化之后的狀態(tài)。

與注解方式注入相比,構(gòu)造器注入可復(fù)用性高,如果使用field注入,缺點(diǎn)顯而易見(jiàn),對(duì)于IOC容器以外的環(huán)境,除了使用反射來(lái)提供它需要的依賴之外,無(wú)法復(fù)用該實(shí)現(xiàn)類。而且將一直是個(gè)潛在的隱患,因?yàn)槟悴徽{(diào)用將一直無(wú)法發(fā)現(xiàn)NPE的存在。

相對(duì)于注解注入,構(gòu)造器注入可以防止循環(huán)依賴的問(wèn)題,若如下代碼:

public class A {
    @Autowired
    private B b;
}
 
public class B {
    @Autowired
    private A a;
}

如果使用構(gòu)造器注入,在spring項(xiàng)目啟動(dòng)的時(shí)候,就會(huì)拋出:

BeanCurrentlyInCreationException:Requested bean is currently in creation: Is there an unresolvable circular reference?

從而提醒你避免循環(huán)依賴,如果是注解注入的話,啟動(dòng)的時(shí)候不會(huì)報(bào)錯(cuò),在使用那個(gè)bean的時(shí)候才會(huì)報(bào)錯(cuò)。

2.3 setter注入

這是在spring3.x出來(lái)的時(shí)候,官方推薦的注入方式,但是在spring4.x以后就沒(méi)有見(jiàn)它推薦了,而且在實(shí)際開(kāi)發(fā)中已經(jīng)很少能見(jiàn)到這種注入方式了。

下面來(lái)看一下它的實(shí)現(xiàn):

@RestController
@RequestMapping("/setter")
public class SetterController {
    private DiService diService; 
    @Autowired
    public void setDiService(DiService diService) {
        this.diService = diService;
    }
 
    @GetMapping("/test001")
    public String test001() {
        return diService.test001("setter");
    }
}

試想一下,一旦需要注入的組件很多,那我們會(huì)累死的,所以大家都不喜歡用它也是情理之中的事情。

這里有一點(diǎn)需要注意:如果通過(guò)set方法注入屬性,那么spring會(huì)通過(guò)默認(rèn)的空參構(gòu)造方法來(lái)實(shí)例化對(duì)象,所以如果在類中寫了一個(gè)帶有參數(shù)的構(gòu)造方法,一定要把空參數(shù)的構(gòu)造方法寫上,否則spring沒(méi)有辦法實(shí)例化對(duì)象,導(dǎo)致報(bào)錯(cuò)。

總結(jié)

這么多的依賴注入方式,我們應(yīng)該怎么選擇呢?那種方式最好呢?

其實(shí),有句古話說(shuō)的很對(duì),合適自己的才是最好的,我們需要看情況來(lái)選擇使用哪種注入方式。

使用構(gòu)造器注入的好處:

  1. 保證依賴不可變(final關(guān)鍵字)
  2. 保證依賴不為空(省去了我們對(duì)其檢查)
  3. 保證返回客戶端(調(diào)用)的代碼的時(shí)候是完全初始化的狀態(tài)
  4. 避免了循環(huán)依賴
  5. 提升了代碼的可復(fù)用性

另外,當(dāng)有一個(gè)依賴有多個(gè)實(shí)現(xiàn)的使用,推薦使用注解方式注入的方式來(lái)指定注入的類型或name,使用setter注入指定類型。這是spring官方博客對(duì)setter注入方式和構(gòu)造器注入的比較

謝謝大家看完了,以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如果有描述不對(duì)的地方歡迎指正,與大家共同進(jìn)步!

相關(guān)文章

  • SpringBoot使用Spring Security實(shí)現(xiàn)登錄注銷功能

    SpringBoot使用Spring Security實(shí)現(xiàn)登錄注銷功能

    這篇文章主要介紹了SpringBoot使用Spring Security實(shí)現(xiàn)登錄注銷功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-09-09
  • 淺析Spring基于注解的AOP

    淺析Spring基于注解的AOP

    Spring是一個(gè)廣泛應(yīng)用的框架,SpringAOP則是Spring提供的一個(gè)標(biāo)準(zhǔn)易用的aop框架,依托Spring的IOC容器,提供了極強(qiáng)的AOP擴(kuò)展增強(qiáng)能力,對(duì)項(xiàng)目開(kāi)發(fā)提供了極大地便利
    2022-11-11
  • java反射機(jī)制實(shí)戰(zhàn)示例分享

    java反射機(jī)制實(shí)戰(zhàn)示例分享

    這篇文章主要介紹了java反射機(jī)制實(shí)戰(zhàn)示例,需要的朋友可以參考下
    2014-03-03
  • Quartz中的Job與JobDetail解析

    Quartz中的Job與JobDetail解析

    這篇文章主要介紹了Quartz中的Job與JobDetail解析,你定義了一個(gè)實(shí)現(xiàn)Job接口的類,這個(gè)類僅僅表明該job需要完成什么類型的任務(wù),除此之外,Quartz還需要知道該Job實(shí)例所包含的屬性;這將由JobDetail類來(lái)完成,需要的朋友可以參考下
    2023-11-11
  • springboot使用JdbcTemplate完成對(duì)數(shù)據(jù)庫(kù)的增刪改查功能

    springboot使用JdbcTemplate完成對(duì)數(shù)據(jù)庫(kù)的增刪改查功能

    這篇文章主要介紹了springboot使用JdbcTemplate完成對(duì)數(shù)據(jù)庫(kù)的增刪改查功能,需要的朋友可以參考下
    2017-12-12
  • JDBC建立數(shù)據(jù)庫(kù)連接的代碼

    JDBC建立數(shù)據(jù)庫(kù)連接的代碼

    這篇文章主要為大家詳細(xì)介紹了JDBC建立數(shù)據(jù)庫(kù)連接的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 簡(jiǎn)述Java圖像傾斜方法及實(shí)例

    簡(jiǎn)述Java圖像傾斜方法及實(shí)例

    這篇文章主要介紹了Java圖像傾斜的方法及實(shí)例,需要的朋友可以參考下
    2017-09-09
  • java簡(jiǎn)明例舉講解泛型

    java簡(jiǎn)明例舉講解泛型

    這篇文章主要介紹了Java的泛型,針對(duì)利用繼承來(lái)實(shí)現(xiàn)通用程序設(shè)計(jì)所產(chǎn)生的問(wèn)題,泛型提供了更好的解決方案,需要的朋友可以參考一下
    2022-04-04
  • java servlet手機(jī)app訪問(wèn)接口(一)數(shù)據(jù)加密傳輸驗(yàn)證

    java servlet手機(jī)app訪問(wèn)接口(一)數(shù)據(jù)加密傳輸驗(yàn)證

    這篇文章主要為大家詳細(xì)介紹了java servlet手機(jī)app訪問(wèn)接口(一),數(shù)據(jù)加密傳輸驗(yàn)證,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 一篇文章教你如何用Java自定義一個(gè)參數(shù)校驗(yàn)器

    一篇文章教你如何用Java自定義一個(gè)參數(shù)校驗(yàn)器

    這篇文章主要介紹了使用java自定義一個(gè)參數(shù)校驗(yàn)器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)
    2021-09-09

最新評(píng)論