主頁 > 後端開發 > Spring 核心概念之一 IoC

Spring 核心概念之一 IoC

2023-06-04 07:44:19 後端開發

前言

歡迎來到本篇文章!通過上一篇什么是 Spring?為什么學它?的學習,我們知道了 Spring 的基本概念,知道什么是 Spring,以及為什么學習 Spring,今天,這篇就來說說 Spring 中的核心概念之一 IoC,

IoC 這個概念對于初學者來說還真不是很好理解,我就是那個理解不了的初學者,那時候,學起來很費解,只是迷迷糊糊知道了一些概念名詞,控制反轉,依賴注入,

現在,我重新梳理這些知識,盡量寫清楚什么是 IoC 以及相關的知識,如有錯誤,敬請指正!好了廢話不多說,進入正題!

什么是 IoC?什么是 Spring IoC 容器?

IoC(Inversion of Control),即控制反轉,也被稱為依賴注入(Dependency Injection,DI)

如果有對「依賴」不太明白的朋友,那么可以去看上一篇,在上一篇中,我們通過 Employee 和 Department 的例子解釋了何為「依賴」

IoC 是一種定義物件之間依賴關系的程序,

在 Spring 沒出現之前,當一個物件需要使用其他物件來完成某些操作,就需要我們自己去創建或查找這些依賴的物件,

現在,有了 Spring,我們的物件交給 Spring 管理,這些物件可以理解為存放在一個容器中的,這個容器就稱為 Spring IoC容器,在 IoC 容器中,物件不再自己管理它們的依賴,而是通過構造方法引數、工廠方法的引數或者在物件創建后通過屬性設定來定義它們的依賴關系

Spring 的 IoC 容器負責在創建物件時注入它們依賴的其他物件,也就是自動地把依賴的物件提供給需要它們的物件,這樣一來,物件不再需要主動去查找或創建它們的依賴,而是由容器在創建物件時幫助它們完成依賴注入的程序,

控制反轉的概念主要是與傳統的直接構造(即 new 操作)來控制物件依賴的方式相反,傳統方式中,一個物件通常會直接創建或查找它所依賴的其他物件,而在 IoC 中,物件將自身的控制權交給了容器,容器負責管理物件的創建和依賴注入,因此被稱為「控制反轉」,

初次見面 BeanFactory 和 ApplicationContext

在 Spring Framework 中,org.springframework.beansorg.springframework.context 包是 Spring IoC 容器的基礎,

下面介紹兩個新手村的伙伴給大家認識,BeanFactory 介面和它的子介面 ApplicationContext 介面,

BeanFactory 介面提供了一個高級配置機制,能夠管理任何型別的物件,

對于它的子介面 ApplicationContext 來說,它的子介面增加了以下功能:

  • 更容易與 Spring AOP 特性集成

  • 訊息資源處理(用于國際化)

  • 事件發布

  • 應用程式層特定背景關系,例如 WebApplicationContext,用于 Web 應用程式,

簡而言之,BeanFactory 提供配置框架和基本功能,而 ApplicationContext 添加了更多企業特定功能,

什么是 Bean?

在 Spring 中,構成應用程式骨干并由 Spring IoC 容器管理的物件稱為 Bean, Bean 是由 Spring IoC 容器實體化、組裝和管理的物件,否則,Bean 只是我們應用程式中眾多物件中的一個普通的物件而已,

Bean 及其相互依賴關系是反映在容器使用的配置元資料(Configuration Metadata)中的,這個配置元資料可以用 XML、Java 注解或 Java 代碼表示,

提示:如果你和我一樣比較喜歡深究這些英文單詞的中文意思,現在的我給你個建議:

就是覺得沒必要深究

比如說 Bean,中文是什么意思,你去找翻譯,發現翻譯是「豆」,還有類似 JavaBean,翻譯是「Java 豆」,這些都是毫無意義的翻譯,所以沒必要知道它的中文意思是什么,Bean 就是 Bean,Bean 就是被 Spring IoC 容器管理的物件,這就是 Bean;JavaBean 則是只提供 setter 和 getter 的純物件,本身沒有任何業務邏輯,這就是 JavaBean,

容器是誰?

我們一直談到「容器」,那么容器到底是什么呢?嘿嘿,容器馬上就揭曉了!

實際上,Spring 的 IoC 容器就是由 org.springframework.context.ApplicationContext 介面來代表的,這個容器承擔著實體化、配置和組裝Bean的責任,

容器通過讀取配置元資料來了解如何創建、配置和組裝物件,同時也允許我們描述應用程式中各個物件之間的復雜依賴關系,目前從本系列的角度來看,我們會使用傳統的 XML 方式來定義配置元資料,這是我們需要學習和了解的,后續才能更好地理解使用 Java 注解或代碼作為配置元資料的方式,

Spring 為我們提供了多個 ApplicationContext 介面的實作,在獨立的應用程式中,常見的實體化方式是創建 ClassPathXmlApplicationContextFileSystemXmlApplicationContext 的一個實體,

不過,在我們日常的開發和作業中,我們基本上不需要顯式地去實體化一個或多個 Spring 容器,特別是在Web應用程式的場景下,通常只需在web.xml檔案中簡單地撰寫約8行標準的XML配置即可完成(你可以參考一些方便的方式來初始化Web應用程式的ApplicationContext),

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

所以,容器終于來啦!它就是 Spring 的 IoC 容器,負責管理 Bean 的實體化、配置和組裝,而我們可以通過配置元資料來描述應用程式中的物件和它們之間的依賴關系,記住,我們一般不需要手動實體化 Spring 容器,特別是在 Web 應用程式中,

Spring IoC 容器怎樣運行的?

從頂層上來看,Spring IoC 是這樣運行的,就是將我們應用程式中的各種業務物件與配置元資料結合起來,使得我們在初始化 ApplicationContext 之后,有一個完整配置的、可用的應用程式,

image-20230525230621539

什么是配置元資料?

先說個結論,目前日常作業中,配置元資料基本都是以 Java 注解或者 Java 代碼的方式來提供給 Spring 容器的,不過 XML 的方式我們也要學習,對于后續學習是有幫助的,

「配置元資料」是 Configuration Metadata,不是 Configure Metadata,這里的「配置」二字是名詞,不是動詞,千萬不要理解成去配置元資料,

這個配置元資料,實際就是用來描述配置的資料,上面我也說了,我們可以用 Java 注解或者 Java 代碼的方式來描述配置,也可以用 XML 的方式來描述資料,

所以現在,相信你已經明白何為配置元資料了,所以學習下以 XML 格式的檔案作為配置元資料,

XML 格式的配置元資料

配置元資料以簡單直觀的 XML 格式提供,這也是本系列前大半部分內容用來傳達 Spring IoC 容器關鍵概念和特性的方式,也正如前面說的,學習 XML 的配置方式,便于我們后續學習 Java 注解或者 Java 代碼的配置方式,

下面的示例展示了基于XML的配置元資料的基本結構

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." >  
        <!-- 該 bean 的協作者和配置寫在此處 -->
    </bean>

    <bean id="..." >
        <!-- 該 bean 的協作者和配置寫在此處 -->
    </bean>

    <!-- 更多的 bean 定義寫在此處 -->

</beans>

上面的示例中,主要使用了 <bean> 元素(或者說標簽),該元素有兩個屬性,idclass

  • id 屬性:它是一個字串,用于標識單個 bean 定義,

  • class 屬性:它定義了 bean 的型別,并使用完全限定類名(又稱全限定名、全類名,多種叫法,都是同一個東西),

我們習慣說把物件交給 Spring IoC 容器管理,那你如何個交法呢

上面的 XML 已經給出了答案,就是定義 Bean,我們每定義一個 Bean,就是將對應的類的物件交給了 Spring IoC 容器了

這些 Bean 的定義就是構成我們應用程式中的各種實際物件,一般我們在開發的時候,都會分層次的,控制層、業務層、持久層、表現層(視圖層)或者其他層次,然后我們就會定義業務層物件、持久層物件、表現層物件等等,

在上一篇中,我舉了個例子,員工和部門的,讓這兩個東西交給了 Spring IoC 管理了,實際上,在日常開發中,是不會這樣做的,不會配置細粒度的領域物件(Domain Object),因為一般這些領域物件都是在業務層和持久層中創建或者加載的,

如何實體化一個 Spring IoC 容器?

上面我也說過,在我們日常的開發和作業中,我們基本上不需要顯式地去實體化一個或多個 Spring 容器的,

但是我們現在在學習,就有必要了解如何手動去實體化一個 Spring IoC 容器,

一行代碼就能夠實體化一個 Spring IoC 容器:

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

在 XML 為配置元資料的情況下,我們可以創建一個 ClassPathXmlApplicationContext 物件,它是 ApplicationContext 的一個實作類,提供給我們的建構式的引數是一潭訓多條路徑是資源字串,它讓容器從各種外部資源(如本地檔案系統、Java CLASSPATH 等)加載配置元資料,這樣我們就實體化一個 Spring IoC 容器,context 物件就是這個容器了,

image-20230602233931031

現在我們將持久層的物件和業務層的物件定義到 XML 中,先創建好需要的類和介面:

image-20230602235701751

接著,在 daos.xml 中定義如下兩個 bean,交給 Spring IoC 管理:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="roleDao" >
        <!-- 該 bean 的協作者和其他配置 -->
    </bean>

    <bean id="userDao" >
        <!-- 該 bean 的協作者和其他配置 -->
    </bean>

    <!-- 其他的持久層的 bean 定義在這里 -->

</beans>

services.xml 同理:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 引入另一個 XML 定義的 bean -->
    <import resource="daos.xml"/>

    <bean id="userService" >
        <property name="userDao" ref="userDao" />
        <property name="roleDao" ref="roleDao" />
    </bean>

    <!-- 其他的業務層的 bean 定義在這里 -->

</beans>

services.xml 中,使用 <import /> 可以讓 Bean 的定義跨越 XML 檔案,一般每個單獨的 XML 組態檔代表了我們應用中的一個邏輯層或者模塊,就如同這里的 daos.xmlservices.xml

使用 Spring IoC 容器

我們把物件交給了 Spring IoC 容器管理,讓它幫我們創建物件以及處理物件之間的依賴關系,

在上面的 XML 中,我們定義了 UserServcie 物件,即把 UserService 這個物件交給了 Spring IoC,那么如何從容器獲取它呢?

ApplicationContext 是一個高級工廠的介面,能夠維護不同 Bean 及其依賴關系的注冊表,我們通過使用方法 T getBean(String name, Class requiredType),就可以獲取到我們需要的 Bean 物件,

代碼如下:

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
UserService userService = context.getBean("userService", UserService.class);
String roleList = userService.getRoleList();
String username1 = userService.getUsernameById(23L);
String username2 = userService.getUsernameById(24L);
System.out.println("roleList = " + roleList + " | username1 = " + username1 + " | username2 = " + username2);

輸出:

image-20230603002316783

總結

以上,就是本文的所有內容,主要講了什么是 Spring IoC 容器,介紹了 BeanFactoryApplicationContext

實際上這個 ApplicationContext 就代表容器,它會讀取我們的配置元資料,這樣它就知道該去管理哪些物件了,

也介紹了什么是 Bean,實際上就是被容器管理的物件,都是所謂的 Bean,也習慣稱為 Bean 物件,

還介紹了 Spring IoC 容器從頂層上來看是怎樣運行的,就是將各種業務物件和配置元資料相結合,組成一個完整配置的、可用的應用程式,

對于配置元資料,這個可以有多種形式,可以是 XML,可以是 Java 注解,可以是 Java 代碼,

最后就介紹了如何去實體化并使用 Spring IoC 容器,雖然我們日常開始是不會這樣去做的,不會去創建一個容器,然后通過容器的 getBean 去獲取 Bean 進行操作,但是我們就是需要了解學習,因為這些就是 Spring 的基礎,

最后的最后

希望各位螢屏前的靚仔靚女們給個三連!你輕輕地點了個贊,那將在我的心里世界增添一顆明亮而耀眼的星!

咱們下期再見!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554219.html

標籤:其他

上一篇:Golang標準庫之bytes介紹

下一篇:返回列表

標籤雲
其他(160278) Python(38201) JavaScript(25474) Java(18185) C(15236) 區塊鏈(8269) C#(7972) AI(7469) 爪哇(7425) MySQL(7226) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5346) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4582) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1981) 功能(1967) HtmlCss(1952) Web開發(1951) C++(1928) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1879) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Spring 核心概念之一 IoC

    歡迎來到本篇文章!通過上一篇什么是 Spring?為什么學它?的學習,我們知道了 Spring 的基本概念,知道什么是 Spring,以及為什么學習 Spring。今天,這篇就來說說 Spring 中的核心概念之一 IoC。 ......

    uj5u.com 2023-06-04 07:44:19 more
  • Golang標準庫之bytes介紹

    本次主要介紹golang中的標準庫`bytes`,基本上參考了 [位元組 | bytes](https://cloud.tencent.com/developer/section/1140520) 、[Golang標準庫——bytes](https://www.jianshu.com/p/e6f7f2 ......

    uj5u.com 2023-06-04 07:44:10 more
  • 執行緒的四個屬性

    ![執行緒各屬性縱覽](https://img2023.cnblogs.com/blog/1220983/202306/1220983-20230603114109107-477345835.png) 如上圖所示,執行緒有四個屬性: - 執行緒ID - 執行緒名稱 - 守護執行緒 - 執行緒優先級 ### 1. ......

    uj5u.com 2023-06-04 07:43:50 more
  • 【python基礎】復雜資料型別-串列型別(排序/長度/遍歷)

    # 1.串列資料元素排序 在創建的串列中,資料元素的排列順序常常是無法預測的。這雖然在大多數情況下都是不可避免的,但經常需要以特定的順序呈現資訊。有時候希望保留串列資料元素最初的排列順序,而有時候又需要調整排列順序。python提供了很多串列資料元素排序的方式,可根據情況選用。 ## 1.永久性排序 ......

    uj5u.com 2023-06-04 07:42:47 more
  • Python潮流周刊#5:并發一百萬個任務要用多少記憶體?

    你好,我是貓哥。這里記錄每周值得分享的 Python 及通用技術內容,部分為英文,已在小標題注明。(標題取自其中一則分享,不代表全部內容都是該主題,特此宣告。) 博客原文:[https://pythoncat.top/posts/2023-06-03-weekly5](https://pythonc ......

    uj5u.com 2023-06-04 07:42:00 more
  • 2022版本IDEA+Maven+Tomcat的第一個程式(傻瓜教學)

    # 2022版本IDEA+Maven+Tomcat的第一個程式(傻瓜教學) ? 作為學習Javaweb的一個重要環節,如何實作在IDEA中利用Maven工具創建一個Javaweb程式模版并連接Tomcat發布是非常重要的。我比較愚鈍(小白),而且自身電腦先前運行過spring或maven的程式,系統 ......

    uj5u.com 2023-06-04 07:35:55 more
  • Java 網路編程 —— 客戶端協議處理框架

    ## 概述 Java 對客戶程式的通信程序進行了抽象,提供了通用的協議處理框架,該框架封裝了 Socket,主要包括以下類: - URL 類:統一資源定位符,表示客戶程式要訪問的遠程資源 - URLConnection 類:表示客戶程式與遠程服務器的連接,客戶程式可以從 URLConnection ......

    uj5u.com 2023-06-03 07:59:45 more
  • 40基于java的美食菜譜分享系統設計與實作

    基于java的美食菜譜分享系統設計與實作,餐飲分享平臺設計與實作,可用于美食在線分享平臺,作為世界各地愛好美食的人們的橋梁,為其創造一個氛圍好的平臺,促進美食世界的文化交流。該系統是一個供商家或者個人推薦美食的網站,網站不支持交易僅供分享。 ......

    uj5u.com 2023-06-03 07:59:40 more
  • celery筆記二之建立celery專案、配置及幾種加載方式

    > 本文首發于公眾號:Hunter后端 > 原文鏈接:[celery筆記二之建立celery專案、配置及幾種加載方式](https://mp.weixin.qq.com/s/KZjuypZ-e9EHi7XkKXt0Xg) 接下來我們創建一個 celery 專案,檔案夾及目錄如下: ```python ......

    uj5u.com 2023-06-03 07:59:34 more
  • 為什么說 Go 語言字串是不可變的?

    **原文鏈接:** [為什么說 Go 語言字串是不可變的?](https://mp.weixin.qq.com/s/AOb6AjKwyTwLeAUou0AU-Q) 最近有讀者留言說,平時在寫代碼的程序中,是會對字串進行修改的,但網上都說 Go 語言字串是不可變的,這是為什么呢? 這個問題本身并 ......

    uj5u.com 2023-06-03 07:59:25 more