成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

騰訊必問的Spring IOC,要看看了!

原創
開發 后端 開發工具
Java 作為流行的開發語言被廣大開發者所青睞,在 Java 平臺提供豐富的應用程序開發功能的同時,其存在的問題也暴露出來。

【51CTO.com原創稿件】Java 作為流行的開發語言被廣大開發者所青睞,在 Java 平臺提供豐富的應用程序開發功能的同時,其存在的問題也暴露出來。

[[411606]]

圖片來自包圖網

這個問題就是其缺乏將基礎組件構建成完整系統的能力,因此開發者需要通過各種設計模式,將開發的組件進行組合,從而構建成最終的應用。

為了解決這個問題,Spring 架構推出了 IoC 組件,它可以通過正規化的方法來組合不同的組件,讓其成為完整的,可以用的應用。

從此開發人員無須手動設置對象的依賴關系,把這一工作交給了 Spring 容器去處理和管理,提升了開發體驗。

今天將圍繞 Spring IoC 給大家講解其實現原理,接下來將會學到如下內容:

  • Spring IoC 的由來和概念
  • Spring IoC 容器
  • Spring IoC 的優缺點
  • IoC 與 DI
  • DI 的自動裝載

Spring IoC 的由來和概念

在介紹 Spring IoC 之前先來看看傳統的對象(組件)依賴是怎么做的,假設通過 RESTFUL 的方式訪問用戶信息(User)。

如圖 1 所示,用戶請求一個 UserController 獲取 User 信息,UserController 會調用 UserService,在 UserService 中會處理關于 User 的業務邏輯。

圖 1:例子依賴關系

同時 UserService 會調用 UserDao,UserDao 負責調用數據庫返回用戶需要的信息。

從這張可以看出 UserController 依賴 UserService、UserService 依賴 UserDao。

如圖 2 所示,假設在 UserController 中需要使用 UserService,就需要在其 UserController 構造函數中對 UserService 進行實例化。

圖 2:傳統的依賴關系需要自己管理對象實例化

這樣才能 save 方法中使用 UserService,并且調用其 save 方法。

與傳統的依賴方式不同,Spring IoC 會通過一個 XML 文件配置對象之間的關系。

如圖 3 所示,在 beans 的標簽中,定義了兩個 bean,分別是 UserController 和 UserService。在 Class 屬性中定義了 Class 的全程(包含 Namespace)。

圖 3:Spring IoC 的依賴關系 XML 配置

需要注意的是在 UserController的bean 定義中指定了 contructor-arg 的 ref 為 UserService。

這里的含義是在 UserController 的構造函數中會引入 UserService,從而說明兩者之間的依賴關系,也就是 UserController 會依賴 UserService。

看完了 XML 的配置再回頭看看代碼中有什么改變,如圖 4 所示,在 UserController 的構造函數的初始化參數中加入 UserService 作為依賴項。

圖 4:Spring IoC 代碼中的改變

不過 New UserService 的動作就不再 UserController 中完成了,而是由 Spring 容器完成。

Spring 容器完成 UserService 的初始化之后,在 UserController 需要使用的時候直接使用這個 UserService 實體就行了。

圖 5:Spring IoC 的 Spring 容器

這里再將 Spring IoC 做的事情梳理一下,如圖 5 所示:

  • 位于中間的 Spring 容器會讀取 XML 配置文件中的信息,獲取 Bean 之間的依賴關系。
  • Spring 容器通過反射機制創建對象的實例,由于 Spring 容器管理所有注冊 Bean 因此為后續建立它們之間的依賴關系打下基礎。
  • Spring 容器通過 Bean 之間的依賴關系創建實例,同時保證 Bean 在使用依賴項的時候直接過去對應的實例,而不用自己去創建實例。

說白了 Spring IoC 做的事情就是管理和創建 Bean 的實例,同時保證 Bean 之間的依賴關系。

這里我們引出 Spring IoC,IoC(Inversion of Control)也稱為控制反轉,也就是對象定義其依賴關系的控制反轉。

原來這個過程是:誰使用誰創建,例如上面的例子中 UserController 需要使用 UserService,于是就由 UserController 創建 UserService 的實例。

引入 IoC 以后,這個創建過程發生的反轉,這些 UserController 和 UserService 之間的依賴關系由 XML 文件定義以后由 Spring 容器進行創建。

這個控制權從對象的使用者轉換為 Spring 容器,就成為控制反轉。也就是對象之間的依賴過程發生了變化,由原來的主動創建,變成了現在被動關聯(因為 Spring 容器的參與),這種控制權顛的現象被稱為控制反轉。

Spring IoC 容器

前面說了 IoC 的來歷和概念,實際上它是用來管理對象初始化的容器,這里會針對 Spring IoC 容器介紹其主要功能。

Spring IoC 容器將創建對象,通過配置設定它們之間的依賴關系,并管理它們的生命周期(從創建到銷毀)。

Spring IoC 容器管理的對象被稱為 Spring Beans,也就是上面例子中提到的 UserController 和 UserService。

通過閱讀配置文件元數據提供的指令,容器知道對哪些對象進行實例化,配置和組裝。

配這里的置元數據就是上面例子的 XML,不過處理 XML 的配置之外還可以通過 Java 注釋或 Java 代碼來表示,大家可以理解為一種配置對象之間關系的方式。

說了這么多的 Spring IoC 容器的作用,在 Spring 中實現 IoC 容器的實際代表者是誰呢?

這里介紹兩類 Spring IoC 容器的代表者,分別是:

①Spring BeanFactory 容器

它是最簡單的容器,用 org.springframework.beans.factory.BeanFactory 接口來定義。

BeanFactory 或者相關的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,在 Spring 中仍然存在具有大量的與 Spring 整合的第三方框架的反向兼容性的目的。

②Spring ApplicationContext 容器

添加了更多的企業特定的功能,例如從一個屬性文件中解析文本信息的能力,發布應用程序事件給感興趣的事件監聽器的能力。

該容器是由 org.springframework.context.ApplicationContext 接口定義。

由于 ApplicationContext 容器包括 BeanFactory 容器的所有功能,同時 BeanFactory 適用于輕量級應用。

這里我們將目光放到 ApplicationContext 容器上,看看它是如何實現 Spring IoC 容器的功能的。

由于 ApplicationContext 是一個接口,針對它有幾種不同的實現,這些實現會針對不同使用場景,以下列出三種不同實現:

FileSystemXmlApplicationContext:實現了從 XML 文件中加載 bean。初始化該類的時候需要提供 XML 文件的完整路徑。

ClassPathXmlApplicationContext:也實現了 XML 文件中加載 bean,與上面一種方式不同的是:不需要提供 XML 文件的完整路徑,只需正確配置 CLASSPATH 環境變量即可,容器會從 CLASSPATH 中搜索 bean 配置文件。

WebXmlApplicationContext:實現了在一個 web 應用程序的范圍內加載在 XML 文件中已被定義的 bean。

由于篇幅原因,這里我們針對 FileSystemXmlApplicationContext 實現 Spring IoC 容器進行說明。

圖 6:FileSystemXmlApplicationContext 實現 Spring IoC 容器

如圖 6 所示:

  • 在使用 FileSystemXmlApplicationContext 實現類之前需要引入相關的包,由于其是接口 ApplicationContext 的實現類,因此需要引入 ApplicationContext 的包,以及自身 FileSystemXmlApplicationContext 的包。
  • 在進行 FileSystemXmlApplicationContext 實例化時傳入 XML 文件的地址,也就是上文中配置 bean 對象的 XML 文件地址,這里是“C:/Test/src/Beans.xml”。
  • 最后通過 FileSystemXmlApplicationContext 所帶的 getBean 方法,通過傳入 bean id 的方式獲取 bean 對象的實例,這里傳入“userController”,從而調用 userController 中的 save 方法完成業務。

Spring IoC 的優缺點

在介紹過 Spring IoC 的原理和容器實現以后,相信大家對 IoC 有所了解了,不過任何技術和架構都有其優缺點 Spring IoC 也不例外在使用它之前,還需要對其有清晰的認識。

首先是優點的部分:

  • 靈活性,由于類之間依賴可以靈活配置,因此可以設置類對于接口的依賴,在針對變現對應的實現類,這種方式讓依賴接口的實現類更加方便,提倡面向接口編程,提高程序的可擴展性。
  • 可讀性,每個bean之間的依賴關系清晰,由于 Spring IoC 容器來管理 bean 的實例,因此不需要創建一堆工廠類來生成不同的 bean。
  • 可測性,由于通過 IoC 的方式讓每個 bean 都解耦了,可以針對單獨的 bean 進行測試,而且 bean 之間的依賴關系也很明確,如果想替換其中的 bean 進行測試也是很容易的事情。

有優點就一定有缺點:

  • 復雜,由于引入 IoC 容器,對象生成步驟變得復雜,本來哪里使用哪里生成對象的,現在憑空多出 XML 配置依賴項之間的關系,讓系統調用變得不太直觀。因此會增加團隊學習成本,需要團隊提升這方面的技能。
  • 性能,IoC 容器生成對象是通過反射方式,在運行效率上有一定的損耗,它允程序在運行時(不是編譯時)對成員進行操作。
  • 配置,IoC 框架需要進行大量的配制工作,無形中會增加開發成本。

IoC 與 DI

前面說了 IoC 及控制反轉,一般來說和 IoC 一同出現的有 DI(Dependency Injection)也就是依賴注入,這兩個概念之間有什么關系呢?

在 2004 年 Martin Fowler 在探索 IOC 控制反轉問題的時候,提出:“哪些方面的控制被反轉了呢?”,經過詳細地分析和論證后,他得出了答案:“獲得依賴對象的過程被反轉了”。

控制被反轉之后,獲得依賴對象的過程由自身管理變為了由 IOC 容器主動注入。

于是,他給“控制反轉”取了一個更合適的名字叫做“依賴注入(Dependency Injection)”。

他的這個答案,實際上給出了實現 IOC 的方法:注入。所謂依賴注入,就是由 IoC 容器在運行期間,動態地將某種依賴關系注入到對象之中。

就好像上面提到的例子一樣,將 UserService 注入到 UserController 一樣,這個過程是由 Spring IoC 容器來完成的。

因此,依賴注入(DI)和控制反轉(IOC)是從不同角度描述同一件事情,就是指通過引入 IOC 容器,利用依賴關系注入的方式,實現對象之間的解耦。

基于對 IoC 和 DI 兩個概念的理解,再來看看實現 DI 的兩種方式:基于構造函數的 DI 和基于 setter 方法的 DI。

基于構造函數的 DI,在上面的例子中提到過這里進行一下回顧,如圖 7 所示,在 XML 的配置文件中定義 UserController 的 bean 同時將 ref 指定 UserService,也就是需要注入的 bean。

圖 7:構造函數 DI 的配置文件

需要注意的是,這里通過設置 contructor-arg 指定構造函數注入方式。

如圖 8 所示,在類文件中 UserController 的構造函數中傳入的參數就是 UserService。

Spring IoC 容器在完成依賴注入和對象初始化以后,在 UserController 中之間使用對象的實例展開后續的業務操作。

圖 8:UserController 使用依賴注入和被初始化以后的 UserService 對象

如圖 9 所示,在配置 bean 節點中稍微做了調整,將 contructor-arg 修改為了 property,通過 property 屬性定義與 UserService 的 setter 方法的依賴關系。

圖 9:UserController 定義 setter 方法的依賴關系

再來看看類中的修改,如圖 10 所示,與構造函數注入方式不同的是,在 UserController 中加入了一個 setUserService 的方法來設置 UserService 的屬性,傳入的參數依舊是 UserService。

圖 10:setter 方法的依賴注入在類中的實現

DI 的自動裝載

上面提到了通過構造函數和 setter 方法來注入備 bean 對象,其分別使用 XML 配置文件中的 和 <:property>元素來完成注入 。

為了減少 XML 配置的數量,Spring 容器可以在不使用 和 <:property>元素的情況下配置 bean 之間的關系, 這種注入的方式稱為自動裝配。

下面我們來看看幾種自動裝配的方式:

①byType,這種方式由屬性數據類型自動裝配

如果在類中定義了與其他類的依賴關系,那么 Spring 容器在 XML 配置文件中會通過類型尋找對應依賴關系的 bean,然后與之關聯。這個過程容器會嘗試匹配和連接屬性的類型。

例如 bean A 定義了 X 類型的屬性, Spring 會在 ApplicationContext 中尋找一個類型為 X 的 bean,并將其注入 bean A。

如果還是覺得抽象,我們看下面的例子,如圖 11 所示,UserController 設置 UserService 屬性時定義了與 UserService 的依賴關系。

圖 11:定義 UserController 與 UserService 的依賴關系

如圖 12 所示,在 XML 配置文件中 UserController 就不需要使用 property 屬性定義與 UserService 之間的關系,取而代之的是使用 autowire=“byType” 的方法。

圖 12:通過 byType 定義關系

容器通過類中 setUserService 傳入的 UserService 類型自動在配置文件中尋找 UserService 對應的類型,從而完成 UserController 和 UserService 依賴關系,也就是依賴注入,這種方式也是基于類型的自動裝載。

②constructor,適用于構造函數參數類型的自動加載

有了 byType 的基礎這個很好理解,例如 bean A 的構造函數接受 X 類型的參數,容器會在 XML 尋找 X 類型的 bean,并將其注入到 bean A 的構造函數中。

如圖 13 所示,UserController 在構造函數中定義 UserService 作為初始化參數,確定了 UserController 對 UserService 的依賴。

圖 13:UserController 在構造函數中定義 UserService 作為初始化參數

如圖 14 所示,在 XML 配置文件中 UserController 只需要設置 autowire=“constructor”。

告訴容器通過 UserController 類中的構造方法將 UserService 注入到 UserController 中,完成 UserController 和 UserService 依賴關系,這種方式也是基于構造器的自動裝載。

圖 14:通過 constructor 定義關系

③byName,通過指定特定的 bean 名稱,容器根據名稱自動選擇 bean 屬性,完成依賴注入

例如:bean A 定義了一個名為 X 的屬性,容器會在 XML 尋找一個名為 X 的 bean,將其注入到 bean A 中。

如圖 15 所示,UserController 中定義了一個名為 myUserService 的成員屬性,其類型是 UserService。

圖 15:UserController 中定義了一個名為 myUserService 的成員屬性

如圖 16 所示,在 XML 的配置中 UserController 的 autowire 配置了“byName”。

此時容器會根據類中定義的 myUserService 成員屬性(變量)自動關聯到 UserService,在 UserController 中 setUserService 時自動裝載 UserService 的實例。

圖 16:XML 文件中 byName 的定義

總結

本文從 Spring IoC 的由來說起,通過一個簡單的對象依賴例子解釋了 Spring IoC 解決的問題。

它將對象的依賴關系從對象內部轉移到了 IoC 容器中完成,由容器來關系對象的注冊和依賴關系。

說起 Spring IoC 容器,由 BeanFactory 和 ApplicationContext 接口完成具體工作。

針對常用的 ApplicationContext 接口的三個實現類,分別實現了根據 XML 加載實例、根據 CLASSPATH 加載實例和根據 Web 應用程序范圍加載實例。

在分析完 IoC 的優缺點以后,解釋了 IoC 與 DI 之間的關系,DI 從另外一個角度解釋了 IoC,它是在 IoC 容器運行期間動態地將依賴關系注入到對象中。

常見的依賴注入方式有:構造函數注入和 setter 方法注入。同時也給大家介紹了 DI 的自動注入(加載),其內容包括 byType、constructor 和 byName 三種。

作者:崔皓

簡介:十六年開發和架構經驗,曾擔任過惠普武漢交付中心技術專家,需求分析師,項目經理,后在創業公司擔任技術/產品經理。善于學習,樂于分享。目前專注于技術架構與研發管理。

編輯:陶家龍

征稿:有投稿、尋求報道意向技術人請聯絡 editor@51cto.com

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

 

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2021-12-13 11:12:41

Spring事務失效

2021-05-20 07:26:21

工具Vuex Vue.js

2010-11-11 11:19:19

騰訊

2021-12-27 08:22:18

Kafka消費模型

2024-03-13 15:41:03

Spring設計IOC

2023-06-30 07:58:07

Spring數據源事務

2023-06-07 08:08:43

JVM內存模型

2020-07-28 08:59:22

JavahreadLocal面試

2021-12-09 12:22:28

MyBatis流程面試

2019-03-15 19:41:39

MySQL面試數據庫

2020-11-05 13:12:47

紅黑樹

2024-01-05 14:20:55

MySQL索引優化器

2021-12-06 11:03:57

JVM性能調優

2023-02-03 07:24:49

雙親委派模型

2009-06-22 10:20:01

Spring IoC容

2023-02-06 07:01:51

2017-09-14 15:09:26

公有云遷移問題

2021-05-07 21:32:51

SpringIOC分析

2019-08-15 23:06:31

2022-12-07 08:02:43

Spring流程IOC
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久久久免费看 | a黄毛片| 久久久资源 | 91国产精品在线 | av大全在线 | 91成人精品视频 | 欧美一区二区三区小说 | 欧美日韩看片 | 精品国产高清一区二区三区 | 91精品国产91久久综合桃花 | 先锋av资源在线 | 国内精品久久久久久影视8 最新黄色在线观看 | 在线中文视频 | 91九色网站| 精品福利在线 | 亚洲一区二区成人 | 国产精品视频一区二区三区不卡 | 成人精品视频免费 | 在线观看亚洲专区 | 色婷婷av99xx| 夜夜av | 亚洲国产一区视频 | 久久在线视频 | 免费一级欧美在线观看视频 | 91精品一区 | 亚洲视频在线观看 | 国产高清在线视频 | 黄网站在线观看 | 久久99国产精品 | 久久人人爽人人爽人人片av免费 | 日韩一区二区免费视频 | 99久久久国产精品 | 久久久免费观看视频 | 久久国产精品免费 | 午夜精品久久久久99蜜 | 51ⅴ精品国产91久久久久久 | 精品二区 | 国产精品三级 | 日韩一级免费电影 | 亚洲欧美一区二区三区1000 | 亚洲免费视频一区 |