Spring核心原理的快速入門:快速了解IoC與DI

IoC

IoC:Inversion of Control(控制反轉)
Spring是一個包含了眾多工具的IoC容器(即bean:spring管理的對象),也就是說Spring 是一個“控制反轉”的容器。
之前是對象本身管理自己的生命周期等等,現在交給spring來管理對象的生命周期

IoC介紹

1.2.1 傳統程序開發

傳統程序開發:一個對象(類)的創建,通常由調用者(使用者)來負責創建的,比如我們創建一個Car對象,通常由Framework來創建,Framework創建Car對象時,如果Car對象需要依賴其他對象(比如Bottom,或者Tire),那么這些依賴對象也需要Framework來創建,并注入給Car對象。

傳統程序開發流程示意圖:

傳統程序開發代碼示例:

public class NewCarExample {public static void main(String[] args) {// 傳統方式:直接創建Car對象Car car = new Car();car.run();}
}// Car.java
public class Car {private Framework framework;public Car() {// Car類內部負責創建其依賴的Framework對象framework = new Framework();System.out.println("Car init...");}public void run() {System.out.println("Car run...");framework.run();}
}// Framework.java
public class Framework {private Bottom bottom;public Framework() {// Framework類內部負責創建其依賴的Bottom對象bottom = new Bottom();System.out.println("Framework init...");}public void run() {System.out.println("Framework run...");bottom.run();}
}// Bottom.java
public class Bottom {private Tire tire;public Bottom() {// Bottom類內部負責創建其依賴的Tire對象this.tire = new Tire();System.out.println("Bottom init...");}public void run() {System.out.println("Bottom run...");tire.run();}
}// Tire.java
public class Tire {private int size;public Tire() {this.size = 17;System.out.println("輪胎尺寸: " + size);}public void run() {System.out.println("Tire run...");}
}

1.2.2 問題分析

在上面的代碼中,我們發現Car對象對Framework類、Bottom類、Tire類有很強的依賴關系。如果這些依賴關系中的任何一個發生變化,比如Car類中需要增加一個依賴對象,或者某個依賴對象的創建方式發生變化(比如Tire需要進行自定義的Size,那么構造方法就需要修改,導致依賴他的所有方法的構造函數都需要修改),那么Car類也需要進行修改。這使得代碼的耦合度很高,不利于代碼的維護和擴展。

具體來說,我們看以下幾點:

  1. Framework類對Car類的依賴: Framework類在main方法中直接創建了Car對象。如果Car類的構造函數發生變化,Framework類也需要修改。這同樣導致了高耦合。
  2. 依賴的傳遞性: 如果Car類又依賴了其他類,那么這些其他類也需要Framework來創建,并注入給Car對象。這樣一來,Framework類就成了整個應用程序的“大管家”,它需要知道所有對象的創建細節,這使得Framework類變得臃腫且難以維護。
  3. 單元測試困難: 由于Car類直接創建了Framework對象,當對Car類進行單元測試時,很難替換掉Framework的真實實現(例如,使用模擬對象)。這使得單元測試變得復雜。
  4. 代碼復用性差: 由于Car類與其需要依賴的類緊密耦合,Car類很難在其他不包含這些被依賴的類的場景下復用。

1.2.3 解決方案

在上面的解決方案中,我們看到針對傳統程序設計模式的缺點,我們可以引入IoC(Inversion of Control) 思想,即控制反轉。IoC的核心思想是:對象的創建和依賴關系的維護不再由調用者負責,而是由一個外部的容器來負責。當調用者需要某個對象時,不再自己去創建,而是向容器請求,容器會負責創建并提供給調用者。

這就像是:以前你餓了,需要自己去廚房做飯(自己創建對象),現在你餓了,只需要告訴餐廳你要什么菜(向容器請求對象),餐廳會幫你做好并送過來(容器創建并提供對象)。這樣,你就不需要關心做飯的細節,只需要關心吃什么。

IoC控制反轉流程示意圖:
在這里插入圖片描述

通過IoC,我們實現了控制反轉,將對象的創建和依賴注入的控制權從應用程序代碼中移出,交給了IoC容器。這樣,應用程序代碼與它所依賴的對象之間的耦合度就大大降低了。

IoC容器就像一個中央工廠,負責管理所有對象的生命周期和依賴關系。當應用程序需要某個對象時,只需向IoC容器聲明其需求,IoC容器就會負責創建該對象及其所有依賴,并將其注入到應用程序中。

IoC容器示意圖:

IoC容器的好處有:

  1. 降低耦合度: 對象之間不再直接依賴,而是通過IoC容器進行解耦。當一個類的依賴發生變化時,不需要修改該類本身的代碼,只需要修改IoC容器的配置。這使得代碼更加靈活,易于維護和擴展。
  2. 提高代碼復用性: 對象不再負責創建自己的依賴,因此可以更容易地在不同的場景下復用。例如,Car類不再其依賴類的創建細節,它可以與任何實現了其依賴類的接口的對象一起使用。
  3. 提高可測試性: 在單元測試中,可以輕松地替換掉真實的對象,使用模擬對象進行測試。這使得單元測試更加簡單和高效。
  4. 簡化配置: IoC容器可以集中管理所有對象的創建和依賴關系,從而簡化了應用程序的配置。開發人員不再需要手動管理大量的對象創建代碼。

1.2.4 IoC程序開發

基于以上思想,我們嘗試用代碼來表示IoC到底是怎么一回事,特別注意受控方式,因為是IoC的關鍵所在。

首先我們先修改一下:

// NewCarExample.java
public class NewCarExample {public static void main(String[] args) {// IoC方式:由外部(模擬IoC容器)創建并注入依賴Tire tire = new Tire();Bottom bottom = new Bottom(tire); // Bottom依賴TireFramework framework = new Framework(bottom); // Framework依賴BottomCar car = new Car(framework); // Car依賴Frameworkcar.run();}
}// Car.java
public class Car {private Framework framework;// 通過構造函數注入依賴public Car(Framework framework) {this.framework = framework;System.out.println("Car create...");}public void run() {System.out.println("Car run...");framework.run();}
}// Bottom.java
public class Bottom {private Tire tire;// 通過構造函數注入依賴public Bottom(Tire tire) {this.tire = tire;System.out.println("Bottom create...");}public void run() {System.out.println("Bottom run...");tire.run();}
}// Tire.java
public class Tire {public Tire() {System.out.println("Tire create...");}public void run() {System.out.println("Tire run...");}
}// Framework.java
public class Framework {private Bottom bottom;// 通過構造函數注入依賴public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("Framework create...");}public void run() {System.out.println("Framework run...");bottom.run();}
}

代碼如上圖所示,我們看到,各個類之間不再直接依賴,而是通過構造器注入的方式,將依賴對象從外部傳入。這使得各個類之間的耦合度大大降低了,并且可以非常容易地進行替換(模擬或真實對象)。當然離真正的IoC容器還有很長的路要走,但思想已經非常接近了。

現在我們再來理一下,Car依賴FrameworkFramework依賴BottomBottom依賴Tire,那么整個依賴關系是:

依賴關系與IoC容器示意圖:

Tire
Bottom
Framework
Car
IoC容器

IoC容器是一個獨立的模塊,它負責創建和管理所有的對象。當一個對象需要另一個對象時,它不再自己去創建,而是向IoC容器請求。IoC容器會負責創建所需的對象,并將它們注入到請求對象中,創建實例的時候不需要了解其中的細節, 降低了使用雙方的的依賴程度,這樣,對象之間就解耦了。

FrameworkBottomTireCar現在都變成了“被動”的對象,它們不再主動去創建自己的依賴對象,而是等待IoC容器將依賴對象注入進來。這種“被動”的特性就是IoC的核心思想。

IoC容器就像一個中央工廠,負責管理所有對象的生命周期和依賴關系。當應用程序需要某個對象時,只需向IoC容器聲明其需求,IoC容器就會負責創建該對象及其所有依賴,并將其注入到應用程序中。

DI

DI: Dependency Injection(依賴注入) 容器在運行期間,動態的為應用程序提供運行時所依賴的資源,稱之為依賴注入。

從這一點來看,依賴注入(DI)和控制逆轉(IoC)是從不同的角度所描述的同一件事,依賴注入是
從應用程序的角度來描述,指通過引入IoC容器,利用依賴關系注入的方式,實現對象之間的解耦

簡單使用

@Component 的作用

@Component 就像給你的類貼上一個“標簽”,告訴Spring: “嘿,Spring!我是一個組件,請你管理我,并且在需要的時候,可以把我的實例提供給別人。”

當Spring掃描到帶有@Component注解的類時,它就會:

  1. 創建并管理這個類的實例(對象)
  2. 將這個實例放入它的“容器”中,隨時準備被其他地方使用。

@Autowired 的作用

@Autowired 就像一個“請求”,告訴Spring: “嘿,Spring!我這里需要一個你管理的某個類型的對象(比如一個BookDao),請你把它“送”給我!”

Spring收到這個請求后,就會從它管理的眾多組件中找到一個匹配的,然后自動把它賦值給你的變量。

結合 @Component@Autowired 的DI流程

  1. 定義組件(@Component:

    @Component // 告訴Spring:我是BookDao,請你管理我
    public class BookDao {// ... 提供數據的方法
    }@Component // 告訴Spring:我是BookService,請你管理我
    public class BookService {// ... 處理業務邏輯的方法
    }
    

現在,BookDaoBookService 的實例都由Spring創建和管理了。

  1. 注入依賴(@Autowired:

    @Component
    public class BookService {@Autowired // 告訴Spring:我需要一個BookDao,請你給我private BookDao bookDao; // Spring會自動把BookDao的實例賦值給它// ...
    }@RestController // @RestController也包含了@Component的功能,所以Spring也會管理它
    public class BookController {@Autowired // 告訴Spring:我需要一個BookService,請你給我private BookService bookService; // Spring會自動把BookService的實例賦值給它// ...
    }
    
    • BookService 不再自己 new BookDao(),而是聲明它需要一個 BookDao,Spring會注入進來。
    • BookController 不再自己 new BookService(),而是聲明它需要一個 BookService,Spring會注入進來。

最終效果: 各個類(BookControllerBookServiceBookDao)之間不再直接創建對方的實例,而是通過Spring這個“中間人”來獲取它們需要的依賴。這使得代碼:

  • 更松散:類與類之間不再緊密耦合。
  • 更靈活:可以輕松替換依賴的實現。
  • 更容易測試:測試時可以注入模擬的依賴。

深入介紹文章:
IoC詳細介紹: here
DI詳細介紹:here

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

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

相關文章

ffmpeg 中config 文件一些理解

依賴檢查 config中看到最多的是: ... nvenc_deps"ffnvcodec" nvenc_deps_any"libdl LoadLibrary" nvenc_encoder_deps"nvenc" ... h264_crystalhd_decoder_select"crystalhd h264_mp4toannexb_bsf h264_parser" h264_cuvid…

Digital Rainwater Collection System (v1.0)

The law doesn’t punish the masses. If only one guy runs his own rainwater system, he gets fined for “illegal mining.” But if millions of households self-host their “digital wells,” the whole centralized model collapses. Cloud providers and regulators …

NFS文件存儲及部署論壇(小白的“升級打怪”成長之路)

目錄 一、概述 NFS掛載原理 NFS工作原理 RPC與NFS通訊過程 二、NFS服務安裝與啟停 NFS服務安裝 NFS服務啟停 三、NFS服務配置文件 四、NFS文件共享配置文件 配置參數說明 五、命令解析 六、客戶端訪問 七、客戶端掛載 實戰案例 部署NFS文件存儲及discuz論壇應用 …

JavaScript 對象創建:new 操作符全解析

引言 在 JavaScript 中,new 操作符是實現面向對象編程的??核心機制??之一。本文將從原理層面對 new 操作符進行深度剖析,探討其工作機制、內部實現和實際應用場景。無論您是 JavaScript 初學者還是資深開發者,都能從本文獲得以下知識和技…

Spring Boot + Vue.js 全棧開發:從前后端分離到高效部署,打造你的MVP利器!

文章目錄一、為何選擇 Spring Boot Vue.js?全棧開發的“黃金搭檔”!二、項目初始化與基礎架構搭建2.1 后端:初始化 Spring Boot 項目2.2 前端:初始化 Vue.js 項目2.3 核心配置:打通前后端通信與跨域!后端 …

容器技術技術入門與Docker環境部署

目錄 一:Docker 概述 1:什么是Docker 2:Docker 的優勢 3:Docker的應用場景 4:Docker核心概念 二:Docker 安裝 三:Docker 鏡像操作 1:獲取鏡像 2:查看鏡像信息 3&#xff1a…

構建高效分布式系統:bRPC組合Channels與HTTP/H2訪問指南

構建高效分布式系統:bRPC組合Channels與HTTP/H2訪問指南 引言 在現代分布式系統中,下游服務訪問的復雜性日益增加。bRPC通過組合Channels和HTTP/H2訪問優化,提供了解決多層級RPC調用、負載均衡和協議兼容性問題的完整方案。本文將深入解析兩大…

WSL創建Ubuntu子系統與 VS code 開發

文章目錄一、打開Windows的虛擬化基礎功能二、安裝WSL和Ubuntu1. 安裝 WSL2. 安裝 Ubuntu三、 VScode一、打開Windows的虛擬化基礎功能 控制面板-程序和功能-啟動或關閉Windows功能,勾選適用于Linux的Windows子系統、虛擬機平臺, 完成后根據提示重啟電腦…

AlpineLinux二進制文件部署prometheus

在Alpine Linux上通過二進制文件部署Prometheus的步驟如下: 創建用戶和組: groupadd prometheus useradd -g prometheus -m -s /sbin/nologin prometheus下載Prometheus二進制文件: 你可以從Prometheus的官方GitHub發布頁面下載最新的二進制文件。例如,使用wget命令: wget…

IoT 小程序:如何破解設備互聯的碎片化困局?

一、IoT 設備管理為何需要輕量化解決方案?隨著物聯網設備規模爆發式增長 —— 預計 2025 年全球連接數將達 270 億臺,傳統 Native 應用開發模式的弊端日益凸顯:某智能家居廠商開發 3 款主流設備 APP,需維護 iOS/Android/ 小程序 3…

Word 怎么讓字變大、變粗、換顏色?

這是Word中最常用也最基礎的操作之一。學會它,你的文檔就會立刻變得重點突出,清晰易讀。 記住一個核心前提:無論做什么格式修改,第一步永遠是【先選中你要修改的文字】。 你可以把鼠標放在文字的開頭,按住左鍵&#xf…

Ruby 安裝 - Linux

Ruby 安裝 - Linux 引言 Ruby 是一種廣泛使用的高級編程語言,以其簡潔、優雅和強大的功能而聞名。在 Linux 系統上安裝 Ruby 是許多開發者的首要任務。本文將詳細介紹如何在 Linux 系統上安裝 Ruby,包括準備工作、安裝過程和常見問題解決。 準備工作 在開始安裝 Ruby 之前…

數組的應用示例

任意輸入【0,9】范圍內的整數&#xff0c;統計輸入的每一種數字的個數并輸出&#xff0c;輸入-1結束程序 #include <stdio.h> int main(){const int number 10;int x;int i;int count[number];for ( i 0; i < number; i){count[i] 0;}printf("請輸入0&#xf…

鴻蒙智行6月交付新車52747輛 單日交付量3651輛

近日&#xff0c;鴻蒙智行公布最新銷量數據&#xff0c;6月單月全系交付52747輛&#xff0c;單日交付量3651輛&#xff0c;分別刷新鴻蒙智行單月、單日銷量歷史新高。僅用39個月實現全系累計交付80萬輛&#xff0c;創下新勢力汽車最快交付紀錄。 尊界S800自5月30日上市以來&…

基于模糊控制及BP神經網絡開關磁阻電機的matlab仿真

1.模型簡介本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2015Rb&#xff09;軟件。2.仿真算法:1&#xff09;采用轉速、轉矩雙閉環控制算法&#xff1b;2&#xff09;外環是速度環&#xff0c;采用改進復合模糊控制&#xff0c;實現速度跟蹤&#xff1b;3&#xff09;…

最新團購源碼商城 虛擬商城系統源碼 全開源

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 最新團購源碼商城 虛擬商城系統源碼 全開源 基于PHP開發的多功能在線商城系統&#xff0c;適合個人、小型企業或創業團隊快速搭建自己的商品銷售平臺。系統界面美觀&#xff0c;功能豐富…

Visual Studio 舊版軟件下載教程

一、前言最近在開發過程中編譯使用Cuda的版本較低&#xff0c;導致與最新的Visual Studio Community 2022 17.14.8不兼容。編譯報錯如下&#xff1a;[cmake] C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\yvals_core.h(902): e…

樂橙亮相2025廣州建博會:用AI重新定義家庭安全與技術邊界

在智能鎖邁入AI新時代的關鍵節點&#xff0c;誰才是真正的技術引領者&#xff1f;2025年廣州建博會&#xff0c;樂橙用一場“不炫技、重本質”的深度展演給出了答案。智哪兒在現場了解到&#xff0c;在A區3.1-28展位&#xff0c;樂橙圍繞“智啟新境 All in Intelligent”這一主…

快速搭建服務器,fetch請求從服務器獲取數據

1.strapi首先strapi是一個api管理系統&#xff0c;可以讓我們直接用網頁的形式去定義自己的api&#xff0c;包括設置模型和權限等功能。首先直接在項目目錄里面安裝庫。npx create-strapilatest server --quickstart這樣就可以直接在項目目錄創建一個連接數據庫的服務器了。不用…

UGF開發記錄_3_使用Python一鍵轉換Excle表格為Txt文本

使用UnityGameFramework日常記錄_3_配一鍵轉換配置表 該系列只做記錄 不做教程 所以文章簡潔直接 會列出碰到的問題和解決方案 只適合UGF萌新 為了提高效率&#xff0c;我使用Python編寫了一個腳本&#xff0c;實現了一鍵將Excel表格批量轉換為帶分隔符的Txt文件&#xff0c…