告別依賴混亂:Spring IoC 容器與 DI 依賴注入入門精講

目錄

什么是 IoC

IoC 介紹

傳統開發思路

解決方法

IoC 優勢

DI

IoC & DI 使用

IoC 詳解

Bean 的存儲

@Controller(控制器存儲)

獲取 bean 對象的其他方法

bean 命名

面試題之 ApplicationContext? pk BeanFactory

@Service(服務存儲)

@Respository(倉庫存儲)

@Component(組件存儲)

@Configuration(配置存儲)

為什么這么多類注解?

方法注解 @Bean

定義多個對象

掃描路徑

DI 詳解

屬性注入(Field Injection)

構造方法注入(Constructor Injection)

Setter 注入(Setter Injection)

三種注入方式的優缺點

@Autowired 存在的問題

使用@Primary:

?@Qualifier 注解:

@Resource 注解:

面試題之 @Autowird 與 @Resource 的區別

Spring,Spring Boot ,Spring MVC

完!


Spring 是包含了眾多工具方法的 IoC 容器

List/Map -> 數據存儲容器

Tomcat -> Web 容器

什么是 IoC

我們在前面已經使用過 IoC 了,在類上面添加 @RestController 和 @Controller 注解,就是把這個對象交給 Spring 管理,Spring 框架啟動的時候,就會加載該類,把對西昂交給 Spring 管理,就是 IoC 思想。

IoC:Inversion of Control(控制反轉),也就是說,Spring 是一個 “控制反轉” 的容器。

控制反轉什么呢??? 獲得依賴對象的過程被反轉了。也就是說,當需要某個對象的時候,傳統開發中,需要我們自己 new 一個對象,現在不需要再進行創建了,把創建對象的任務交給了容器。我們在程序中,只需要進行依賴注入即可~~ 這個容器,就稱為 IoC 容器,所以有時 Spring 也被稱為 Spring 容器。

IoC 介紹

我們以一個具體案例來了解 IoC 思想。

當我們需要造一輛車的時候。

傳統開發思路

先設計輪子,然后根據輪子的大小設計底盤,再根據底盤設計車身,再根據車身,對整個汽車進行設計。這樣一層一層設計,就會出現一個依賴關系 ,即汽車依賴車身,車身依賴底盤,底盤依賴輪子。

上面的設計的可維護性非常低。當我們的需求發生一些變化的時候,隨著對車的需求量越來越大,個性化需求也會越來越多,需要加工更多尺寸的輪胎,就需要對程序進行修改了。

即問題是:當最底層的代碼發生改動之后,調用鏈上的所有代碼,都需要進行修改。程序的耦合度極高,修改一處代碼,會影響其他處的代碼~~

解決方法

上面程序中,我們根據輪子的尺寸設計底盤,輪子尺寸修改,底盤就需要修改,同樣的,后面的車身,汽車都需要修改。

我們可以先設計汽車的大概樣子,然后根據汽車來設計車身,根據車身設計底盤,根據底盤設計輪子。

我們可以嘗試,不在每個類中創建自己的下積累,如果自己創建下級類,當下級類發生改變操作的時候,我們自己也要跟著修改。

改用傳遞(注入)的方式。

IoC 優勢

傳統代碼中創建對象的順序是:Car->Framework->Bottom->Tire

改進解耦合之后的順序是:Tire->Bottom->Framework->Car

改進之后,創建對象的控制權發生了反轉,不再是使用方來進行對象創建并且控制依賴對象了,而是把依賴對象注入到當前對象中,依賴對象的控制權不再由當前類進行控制了。

這部分代碼,就算 IoC 容器所作的工作。

IoC 容器可進行資源的幾種管理,實現資源的可配置和易管理,當我們需要使用的時候,只需要從容器中取就可以了

IoC 容器也降低了使用資源雙方的依賴程度,創建實例的時候并不需要了解細節,實現了解耦合~~

DI

DI:Dependency Injection (依賴注入)

容器在運行期間,動態的為應用程序提供運行時所依賴的資源。依賴注入是從應用程序的角度進行描述,指通過引入?IoC 容器,利用依賴關系注入的方式,實現對象之間的解耦合

IoC & DI 使用

Spring 是一個 IoC 容器,管理的主要是對象,這些對象,我們稱之為 Bean。Spring 來負責這些對象的創建和銷毀,我們程序只需要告訴 Spring,那些需要存,以及如何從 Spring 中取出對象。

實現:

1. 把 BookDao 交給 Spring 管理,在 BookDao 類前添加 @Component 注解

2. 把 BookService 交給 Spring 管理,由 Spring 來管理對象

3. 刪除 BookService 中創建 BookDao 的代碼,從 Spring 中獲取對象,添加 @Autowired 注解

4. 刪除 BookController 中創建?BookService 的代碼,從 Spring 中獲取對象,添加 @Autowried 注解

IoC 詳解

系統的學習 Spring IoC 和 DI 操作。前面提到的 IoC 控制反轉,就是將對象的控制權交給 Spring 的 IoC 容器,由它對對象進行創建和管理。

也就是 bean 的存儲。

Bean 的存儲

之前的案例中,我們要把對象交給 IoC 容器管理,需要在類上添加一個注解:@Component?

Spring 框架中,提供了更豐富的注解。

@Controller(控制器存儲)

從 Spring 容器中獲取對象

補充:因為我們的對象通過 @Controller 注解都交給 Spring 管理了,所以獲取對象要通過 Spring 獲取,那么就需要先得到 Spring 的上下文,即 ApplicationContext 翻譯就是 Spring 上下文~

此時,如果我們把 @Controller 刪掉,運行結果如下:

表明在 Spring 中找不到指定類型的 Bean

獲取 bean 對象的其他方法

通常使用 1 2 4 三種方式獲取 bean,且獲取到的 bean 都是一致的

其中 1 2 都涉及到根據名稱來獲取對象,再來研究一下 bean 命名約定~

bean 命名

官方文檔中寫道:程序開發人員并不需要為 bean 指定名稱,如果沒有顯示的提供名稱,Spring 容器會為該 bean 生成唯一的名稱。

命名約定就使用 Java 標準約定作為實例字段名。即,bean 名稱以小寫字母開頭,然后使用駝峰式大小寫~

也有特殊情況,即,當由多個字符,且第一個和第二個字符都是大寫的時候,將會保留原始的大小寫~

我們根據規則,再來進行 bean 的獲取:

三條 sout 語句的結果一致

地址一樣,說明對象是同一個~

面試題之 ApplicationContext? pk BeanFactory

繼承關系和功能方面:Spring 容器的兩個頂級的接口:BeanFactory 和 ApplicationContext。其中,BeanFactory 提供了基礎的訪問容器的能力,ApplicationContext 屬于 BeanFactory 的子類,出了繼承了 BeanFactory 的功能之外,還有了其他方面的特性~

性能方面:BeanFactory 是懶加載,用到那個加載那個。ApplicationContext 是一次性加載并初始化所有的 Bean 對象~

@Service(服務存儲)

去掉 @service 注解后,仍然報錯:

@Respository(倉庫存儲)

@Component(組件存儲)

@Configuration(配置存儲)

為什么這么多類注解?

@Controller:控制層,接收請求,對請求進行處理,并進行響應。

@Service:業務邏輯層,處理具體的業務邏輯。

@Respository:數據訪問層,負責數據訪問操作

@Configuration:配置層,處理項目中的一些配置信息

當我們對五大類注解的源碼進行觀察后

除 @component 之外,剩下四個注解的源碼中均有 @Component 注解。說明他們本身都是屬于 @Component 的子類,@Component 是一個元注解,可以對其他注解進行注解~~

剩下四個注解,可以被稱為 @Component 的衍生注解~~

其實從功能上來說,五大注解大差不多可以混用,但是在邏輯上是不可以的~~

方法注解 @Bean

類注解是添加到某個類上的,但有兩個問題:

????????1. 使用外部包中的類,沒辦法添加類注解

? ? ? ? 2. 一個類,需要多個對象,多個數據源~

這種情況,我們需要使用 @Bean 注解

?

結果如下:

方法注解是要配合類注解進行使用的。

在 Spring 框架的設計中,方法注解 @Bean 要配合類注解才能將對象正常的存儲到 Spring 容器中

定義多個對象

即,多數據源的情況,類是同一個,但配置不同,指向不同的數據源

此時,我們根據類型獲取對象:

運行結果:

期望是獲取到唯一一個匹配,結果發現了兩個 user1 和 user2

從報錯信息來分析,@Bean 注解的 bean,其名稱就是它的方法名。

根據名稱來獲取 bean 對象:

此時可以成功獲取到~

也可以對 bean 的名稱進行重命名

掃描路徑

Q:使用前面我們提到的四個注解生命的 bean,一定會生效嗎?

A:不一定(bean 要想生效,還需要被 Spring 掃描到)

其他代碼不懂,僅僅修改目錄結構:

又會發現,找不到名稱為 u1 的 bean。

使用五大注解聲明的 bean,要想生效,還需要配置掃描路徑,讓 Spring 掃描到這些注解~

使用 @ComponentScan 來配置掃描路徑

這種做法僅作了解~

那為什么前面我們并沒有配置這個直接,也可以正常使用呢?

@SpringBookApplication 這個啟動類聲明注解中,已經包含 @ComponentScan 注解了~

會默認掃描 SpringBoot 啟動類所在的包及其子包~

一般我們將啟動類直接放在我們要被掃描的包的路徑下即可~

DI 詳解

依賴注入是一個過程,值 IoC 容器在創建 Bean 的時候,去提供運行時所依賴的資源(對象)

上面案例中,我們是使用了? @Autowired 注解,完成了依賴注入的操作。

簡單來說,就是把對象取出來,放入某個類的屬性中。

依賴注入,Spring 也提供了三種方式

屬性注入(Field Injection)

屬性注入是使用 @Autowired 實現的,將 Service 類注入到 Controller 類中

運行結果:

去掉 @Autowired 的時候,結果如下:空指針異常,找不到 userService

構造方法注入(Constructor Injection)

注:

? ? ? ? 1. 如果只有一個構造函數的情況下,@Autowired 可以省略

? ? ? ? 2. 如果有多個構造函數,需要指定默認的構造函數(@Autowired 指定)如果未指定,則默認使用無參的構造函數

? ? ? ? 3. 構造函數規范:如果添加構造函數,把無參構造函數顯示的進行添加~

Setter 注入(Setter Injection)

Setter 注入和屬性的 Setter 方法實現類似,只不過在設置 set 方法時候,需要加上 @Autowired 注解

三種注入方式的優缺點

@Autowired 存在的問題

當同一個類中,存在多個 bean 的時候,使用 @Autowired 會存在問題

運行結果:

報錯的原因是:非唯一的 Bean 對象

解決方案:

@Primary

@Qualifier

@Resource

使用@Primary

當存在多個相同類型的 Bean 注入時候,加上 @Primary 注解,來確認默認的實現~

?@Qualifier 注解

指定當前要注入的 bean 對象。在 @Qualifier 的 value 屬性中,指定注入的 bean 的名稱

注:Qualifier 注解不能單獨使用,需要搭配 @Autowired 使用

@Resource 注解:

是按照 bean 的名稱進行注入。通過 name 屬性指定要注入的 bean 的名稱

面試題之 @Autowird 與 @Resource 的區別

1. @Autowired 是 Spring 框架提供的注解,而 @Resource 是 jdk 提供的注解

2 @Autowired 默認是按照類型注入的,而 @Resource 是按照名稱注入,相比 @Autowired 來說,@Resource 支持更多的參數設置~

Spring,Spring Boot ,Spring MVC

?

完!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/98062.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/98062.shtml
英文地址,請注明出處:http://en.pswp.cn/web/98062.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

視頻理解學習筆記

目錄 VideoRefer VideoPrism 核心解密:通用視頻編碼器的力量 VideoRefer VideoRefer 是由浙江大學和阿里達摩院聯合推出的視頻對象感知與推理技術,增強視頻大型語言模型(Video LLMs)的空間-時間理解能力。簡單一點來說就是可以…

P1198題解

題目鏈接 開題第一件事看數據范圍.這里的范圍是二十萬,支持O(nlogn). 這是一個RMQ問題,同時要加點,我們因此考慮ST表或者線段樹.這里用線段樹是核彈打蚊子,沒有意義,我們因此考慮ST表.我們注意到如果加點操作需要改動ST表原來的東西ST表就會炸掉,我們就要考慮更高級的數據結構…

使用yolov8對視頻進行目標檢測

使用 Ultralytics 的 YOLO 模型對視頻進行逐幀目標檢測非常簡單,以下是完整的實現方法: 我們的輸入視頻是這樣的 視頻目標檢測輸入視頻這里是天津市和平區天津大學附近,感興趣的小伙伴來天津玩哈!! 1. 安裝依賴 確保已…

Edge瀏覽器的自動化點擊系統

Tag_click_openclose_V6 開發與使用注意事項 網頁自動化點擊系統 一個基于Python和CustomTkinter開發的桌面應用程序,通過Selenium實現對Edge瀏覽器的自動化控制。點擊Tag_click_openclose_V6進入Github自取,記得點贊收藏嗷。 功能介紹 連接到已打開…

Python股票數據分析與預測系統 LSTM神經網絡算法 股票價格預測 Tensorflow深度學習 機器學習 Flask框架 東方財富(建議收藏)?

博主介紹:?全網粉絲50W,前互聯網大廠軟件研發、集結碩博英豪成立軟件開發工作室,專注于計算機相關專業項目實戰6年之久,累計開發項目作品上萬套。憑借豐富的經驗與專業實力,已幫助成千上萬的學生順利畢業,…

英萊科技焊縫跟蹤系統亮相德國埃森焊接展,激光視覺點亮世界舞臺

9月15-19日,每4年一屆的德國埃森焊接與切割展覽會(SCHWEISSEN & SCHNEIDEN)即將盛大開幕。作為焊接行業最具規模及權威性的盛會之一,英萊科技將攜全新PF系列激光視覺焊縫跟蹤系統驚艷亮相,為全球智能化焊接貢獻中國…

嵌入式基本概念:什么是指令集,微架構,IDE,DFP等等是什么意思,有什么關系???

注:下面是指令集和微框架的分類圖,后面我會以ARM的M4舉例子。 一.什么是指令集 大概的可以看這個視頻 https://www.bilibili.com/video/BV1uXzbYBEy2/?spm_id_from333.1007.top_right_bar_window_custom_collection.content.click&vd_source406ed…

Spring Cloud之服務入口Gateway之自定義過濾器

目錄 過濾器執行順序 自定義過濾器 自定義GatewayFilter 定義GatewayFilter 配置過濾器 啟動服務并訪問 自定義GlobalFilter 定義GlobalFilter 啟動服務并訪問 服務部署 過濾器執行順序 如果?個項?中, 既有GatewayFilter, ?有 GlobalFilter時, 執?的先后順序是什…

MySQL——視圖、儲儲過程、觸發器

目錄 一、視圖 二、存儲過程 三、觸發器 一、視圖 視圖是一種虛擬存在的表。視圖中的數據并不在數據庫中真實存在,行和列數據來自定義視圖的查詢中使用的表,并且是在使用視圖時動態生成的。通俗的講,視圖只保存了查詢的SQL邏輯&#xff0c…

iOS App 卡頓與性能瓶頸排查實戰 如何定位CPU內存GPU幀率問題、優化耗電與網絡延遲(uni-app開發性能優化全流程指南)

在 iOS 應用開發中,卡頓 是用戶最直觀的負面體驗。 一個 App 如果在頁面切換、滾動、后臺運行時頻繁掉幀或發熱,用戶很快就會放棄使用。 對于 uni-app 跨平臺開發者 來說,卡頓問題更為復雜: JS 與原生層橋接增加了 CPU 負載&#…

騰訊開源多模態 RAG:復雜文檔秒變自建知識庫,支持 API 調用

上篇,分享了 小智AI MCP系列的第一篇: 小智 AI 鬧鐘提醒 定時任務,設備端MCP實現 有朋友問,能否接入知識庫 RAG? 讓小智可以根據企業知識庫,回答客戶的疑問~ 當然可以,接入方式同樣是 MC…

Node.js中的 http 模塊詳解

http 模塊是 Node.js 中的核心模塊之一,專門用于構建基于 HTTP 的網絡應用程序。它允許創建 HTTP 服務器和客戶端,處理網絡請求和響應。1. 核心 API 詳解1.1. http.createServer([options][, requestListener])用于創建 HTTP 服務器的核心方法&#xff0…

LAMP 環境部署

LAMP 環境部署 一、概述 1. 目的 基于 CentOS 7 系統部署 LAMP(Linux Apache MySQL PHP)環境的完整步驟,通過腳本化操作實現環境快速搭建,適用于運維人員進行測試環境或基礎生產環境的 LAMP 部署 2. 適用環境操作系統&#xff…

用html5仿造nes游戲敲玻璃寫一個敲玻璃游戲

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>敲玻璃游戲</title><style>body {ma…

996引擎-ItemTips特效框層級自定義

996引擎-ItemTips特效框層級自定義 需求場景 ItemTips 中相關方法 創建特效的位置 創建特效框 核心修改 調整視圖,自己加個背景,不用原來的 設置 tipsLayout_bg 的層級 結果預覽 參考資料 需求場景 策劃說我們的tips特效框,遮擋文字。如果按官方說的設為底層又跑到背景框后…

Java 注解與 APT(Annotation Processing Tool)

Java 注解與 APT&#xff08;Annotation Processing Tool&#xff09; 注解&#xff08;Annotation&#xff09;基礎 注解是 Java 語言的一種元數據形式&#xff0c;它可以在代碼中添加標記信息&#xff0c;用于描述代碼的額外信息&#xff0c;但不會直接影響代碼的執行邏輯。注…

Unity 檢測網絡-判斷當前(Android/Windows平臺)設備是否連接了指定WiFi

判斷設備是否連接了特定的網絡1.Unity 腳本2.Unity AndroidManifest.xml文件①改個設置②補充權限語句1.Unity 腳本 using UnityEngine; using System.Collections; using System.Diagnostics; using Debug UnityEngine.Debug; using UnityEngine.UI;#if UNITY_ANDROID &…

通過網絡強化增強混合IT環境的安全

網絡是企業運營的支柱&#xff0c;也是網絡犯罪分子和惡意威脅者的主要目標&#xff0c;他們會破壞IT運營的連續性。隨著混合云基礎設施、遠程辦公和物聯網&#xff08;IoT&#xff09;生態系統的出現&#xff0c;網絡邊界正在不斷擴大&#xff0c;新的漏洞不斷產生&#xff0c…

ACP(四):RAG工作流程及如何創建一個RAG應用

RAG的工作原理 你在考試的時候有可能會因為忘記某個概念或公式而失去分數&#xff0c;但考試如果是開卷形式&#xff0c;那么你只需要找到與考題最相關的知識點&#xff0c;并加上你的理解就可以進行回答了。 對于大模型來說也是如此&#xff0c;在訓練過程中由于沒有見過某個知…

宇視設備視頻平臺EasyCVR視頻設備軌跡回放平臺監控攝像頭故障根因剖析

監控攝像頭的類型繁多&#xff0c;市場上提供了廣泛的選擇。然而&#xff0c;在使用監控攝像頭的過程中&#xff0c;用戶可能會遇到云臺在很短的時間內出現運轉不靈或完全無法轉動的問題。這里&#xff0c;我們將對這一常見問題進行深入分析。一、具體的原因&#xff1a; 1、距…