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

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

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

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

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

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

二.DI的三種常見注入方式

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

2.1 基于注解注入

首先來看一下它的實現(xiàn):

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

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

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

2、使得整體代碼簡潔明了,看起來美觀大方。

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

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

下面進入正題:

注解方式注冊bean:

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

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

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

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

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

關(guān)于他們的具體用法與區(qū)別,因為內(nèi)容比較多,所以寫在另一篇博客中,請見:@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);
    }
}

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

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

官方文檔里是這么說的:

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團隊通常提倡構(gòu)造函數(shù)注入,因為它允許將應(yīng)用程序組件實現(xiàn)為不可變的對象,并確保所需的依賴不為空。此外,注入構(gòu)造函數(shù)的組件總是以完全初始化的狀態(tài)返回給客戶機(調(diào)用)代碼。

簡單解釋一下:

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

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

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

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

如果使用構(gòu)造器注入,在spring項目啟動的時候,就會拋出:

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

從而提醒你避免循環(huán)依賴,如果是注解注入的話,啟動的時候不會報錯,在使用那個bean的時候才會報錯。

2.3 setter注入

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

下面來看一下它的實現(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");
    }
}

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

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

總結(jié)

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

其實,有句古話說的很對,合適自己的才是最好的,我們需要看情況來選擇使用哪種注入方式。

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

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

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

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

相關(guān)文章

  • 基于resty?security的Api權(quán)限控制與事務(wù)支持

    基于resty?security的Api權(quán)限控制與事務(wù)支持

    這篇文章主要為大家介紹了基于resty?security的Api權(quán)限控制與事務(wù)支持讓數(shù)據(jù)操作處于事務(wù)控制下,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • Java?SpringTask定時自動化處理方法

    Java?SpringTask定時自動化處理方法

    這篇文章主要介紹了Java?SpringTask定時自動化處理,通過自動化,不僅可以提高工作效率和準(zhǔn)確性,還可以釋放人力資源以專注于更高價值的工作,需要的朋友可以參考下
    2024-08-08
  • springboot+redis 實現(xiàn)分布式限流令牌桶的示例代碼

    springboot+redis 實現(xiàn)分布式限流令牌桶的示例代碼

    這篇文章主要介紹了springboot+redis 實現(xiàn)分布式限流令牌桶 ,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Java使用Callable接口實現(xiàn)多線程的實例代碼

    Java使用Callable接口實現(xiàn)多線程的實例代碼

    這篇文章主要介紹了Java使用Callable接口實現(xiàn)多線程的實例代碼,實現(xiàn)Callable和實現(xiàn)Runnable類似,但是功能更強大,具體表現(xiàn)在可以在任務(wù)結(jié)束后提供一個返回值,Runnable不行,call方法可以拋出異,Runnable的run方法不行,需要的朋友可以參考下
    2023-08-08
  • MyBatis字段名和屬性名不一致的解決方法

    MyBatis字段名和屬性名不一致的解決方法

    本文主要介紹了MyBatis字段名和屬性名不一致的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • java集合類ArrayList和Vector的區(qū)別面試精講

    java集合類ArrayList和Vector的區(qū)別面試精講

    這篇文章主要為大家介紹了java集合類ArrayList和Vector的區(qū)別面試全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • 詳解Spring Boot實戰(zhàn)之Rest接口開發(fā)及數(shù)據(jù)庫基本操作

    詳解Spring Boot實戰(zhàn)之Rest接口開發(fā)及數(shù)據(jù)庫基本操作

    本篇文章主要介紹了Spring Boot實戰(zhàn)之Rest接口開發(fā)及數(shù)據(jù)庫基本操作,具有一定的參考價值,有興趣的可以了解一下
    2017-07-07
  • SpringBoot超詳細講解多數(shù)據(jù)源集成

    SpringBoot超詳細講解多數(shù)據(jù)源集成

    今天分享下SpringBoot多數(shù)據(jù)源集成,我怕麻煩,這里我覺得我的集成也應(yīng)該是最簡單的,清晰明了
    2022-05-05
  • Java?使用geotools讀取tiff數(shù)據(jù)的示例代碼

    Java?使用geotools讀取tiff數(shù)據(jù)的示例代碼

    這篇文章主要介紹了Java?通過geotools讀取tiff,一般對于tiff數(shù)據(jù)的讀取,都會借助于gdal,本文結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • 深入理解JAVA多線程之線程間的通信方式

    深入理解JAVA多線程之線程間的通信方式

    下面小編就為大家?guī)硪黄钊肜斫釰AVA多線程之線程間的通信方式。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05

最新評論

思茅市| 宜州市| 洪雅县| 大荔县| 安西县| 邹城市| 大方县| 邮箱| 贵阳市| 庄河市| 双鸭山市| 邵东县| 汉源县| 柘荣县| 望江县| 青州市| 锦州市| 崇明县| 新野县| 耿马| 台湾省| 浦北县| 城口县| 江阴市| 综艺| 思茅市| 河津市| 达孜县| 濮阳市| 休宁县| 罗定市| 乐平市| 新津县| 卓资县| 衢州市| 金昌市| 沁源县| 沂南县| 凯里市| 恩施市| 大方县|