日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

spring DI的三种注入方式分析

發(fā)布時(shí)間:2023/12/20 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring DI的三种注入方式分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

Spring框架對(duì)Java開(kāi)發(fā)的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反轉(zhuǎn))和AOP,平時(shí)使用最多的就是其中的IOC,我們通過(guò)將組件交由Spring的IOC容器管理,將對(duì)象的依賴(lài)關(guān)系由Spring控制,避免硬編碼所造成的過(guò)度程序耦合。
在講依賴(lài)注入之前,我覺(jué)得有必要了解一下IOC(控制反轉(zhuǎn))與DI(依賴(lài)注入)的關(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 {@Autowiredprivate DiService diService;@GetMapping("/test001")public String test001() {return diService.test001("annotation");} }

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

  • 注入方式非常簡(jiǎn)單:加上@Autowired注解,加入要注入的字段,即可完成。
  • 使得整體代碼簡(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ù)類(lèi)型一致的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名稱(chēng)的第一個(gè)單詞首字母必須小寫(xiě),這一點(diǎn)與手動(dòng)set注入有點(diǎn)不同。
    • byType:查找所有的set方法,將符合符合參數(shù)類(lèi)型的bean注入。

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

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

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

  • @Component:可以用于注冊(cè)所有bean
  • @Repository:主要用于注冊(cè)dao層的bean
  • @Controller:主要用于注冊(cè)控制層的bean
  • @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容器中。

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

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

    關(guān)于他們的具體用法與區(qū)別,因?yàn)閮?nèi)容比較多,所以寫(xiě)在另一篇博客中,請(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ù)類(lèi)型與注入的bean的類(lèi)型匹配,那就會(huì)注入到該構(gòu)造方法中。如果有多個(gè)有參數(shù)的構(gòu)造方法并且每個(gè)構(gòu)造方法的參數(shù)列表里面都有要注入的屬性,那userDaoJdbc會(huì)注入到哪里呢?

    ?

    在Spring4.x版本中推薦的注入方式就是這種,相較于上面的field注入方式而言,就顯得有點(diǎn)難看,特別是當(dāng)注入的依賴(lài)很多(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ì)象,并確保所需的依賴(lài)不為空。此外,注入構(gòu)造函數(shù)的組件總是以完全初始化的狀態(tài)返回給客戶(hù)機(jī)(調(diào)用)代碼。

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

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

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

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

    public class A {@Autowiredprivate B b; }public class B {@Autowiredprivate 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)依賴(lài),如果是注解注入的話,啟動(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;@Autowiredpublic 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ì)象,所以如果在類(lèi)中寫(xiě)了一個(gè)帶有參數(shù)的構(gòu)造方法,一定要把空參數(shù)的構(gòu)造方法寫(xiě)上,否則spring沒(méi)有辦法實(shí)例化對(duì)象,導(dǎo)致報(bào)錯(cuò)。

    總結(jié)

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

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

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

  • 保證依賴(lài)不可變(final關(guān)鍵字)
  • 保證依賴(lài)不為空(省去了我們對(duì)其檢查)
  • 保證返回客戶(hù)端(調(diào)用)的代碼的時(shí)候是完全初始化的狀態(tài)
  • 避免了循環(huán)依賴(lài)
  • 提升了代碼的可復(fù)用性
  • 另外,當(dāng)有一個(gè)依賴(lài)有多個(gè)實(shí)現(xiàn)的使用,推薦使用注解方式注入的方式來(lái)指定注入的類(lèi)型或name,使用setter注入指定類(lèi)型。這是spring官方博客對(duì)setter注入方式和構(gòu)造器注入的比較。謝謝大家看完了,如果有描述不對(duì)的地方歡迎指正,與大家共同進(jìn)步!

    總結(jié)

    以上是生活随笔為你收集整理的spring DI的三种注入方式分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 中文字幕蜜臀 | 日韩黄色三级 | 国产精久久久久 | 爽爽视频在线观看 | 日韩欧美一级二级 | 一本一本久久a久久精品综合麻豆 | 刘亦菲一区二区三区免费看 | 国产欧美日韩综合精品一区 | 国产精品jizz在线观看无码 | 欧美91精品久久久久国产性生爱 | 欧美性大战久久久久xxx | 欧美成人三级在线观看 | 欧美激情校园春色 | 老司机精品视频在线 | 欧美午夜在线观看 | 国产极品粉嫩 | 国产亚洲性欧美日韩在线观看软件 | 国产69精品久久久久777 | 日本中文在线 | 日本精品一区二区视频 | av影片在线 | 4438x在线观看 | 麻豆一区产品精品蜜桃的特点 | 91麻豆精品国产91久久久久久 | 青青草香蕉 | 国产又大又粗又硬 | 中文字幕一区二区免费 | 国模视频一区 | 五月99久久婷婷国产综合亚洲 | 野外吮她的花蒂高h在线观看 | 国产精品无码久久久久久 | 精品人妻aV中文字幕乱码色欲 | 色不卡 | 羞羞成人 | 福利在线网站 | 亚洲三区在线 | 五月激情六月丁香 | 久久精品一日日躁夜夜躁 | 国产成人亚洲精品无码h在线 | 亚洲免费一二三区 | 日本在线精品视频 | 日本va欧美va国产激情 | 韩日av网站 | 色视频一区二区 | 久久婷婷五月综合色吧 | 黄色污污视频软件 | 三点尽露的大尺度国产 | 亚洲精品1区 | 欧美浪妇xxxx高跟鞋交 | 91免费视频网址 | 成人在线免费高清视频 | 久久精品欧美一区二区三区麻豆 | 91视频官网 | 那里可以看毛片 | 国产亚洲精品美女久久久久 | www.av黄色 | 香蕉久热| 99精品免费视频 | 亚洲福利一区二区三区 | 国产精品第七页 | 91 色| 国产区久久 | 中文字幕日韩一区二区三区 | 一本色综合 | 老公吃小头头视频免费观看 | 欧美一区二区三区免费在线观看 | 欧美久久久久久久久久久久 | 亚洲欧美一二三 | 无码人妻久久一区二区三区不卡 | 精品国偷自产国产一区 | 人与动物2免费观看完整版电影高清 | 欧美日韩成人免费 | 九热在线视频 | 91大神福利视频 | 韩国av免费观看 | 欧美一区网站 | 色屁屁 | 69久久成人精品 | 免费视频一区二区 | 美女黄免费| 亚洲草逼 | 国产1区2区3区4区 | 双性皇帝高h喷汁呻吟 | av成人免费| 色撸撸在线 | 高级家教课程在线观看 | 天美视频在线观看 | 一区二区三区久久久久 | 朝桐光在线观看 | 久久久丁香| 国产av 一区二区三区 | 日韩精品一区二 | 色窝窝无码一区二区三区成人网站 | 中国少妇高潮 | av不卡免费在线 | 国产精品99久久久久久动医院 | 大奶子情人 | 久久久久逼 | 亚洲成人自拍偷拍 |