前言
歡迎來到本篇文章!通過上一篇什么是 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.beans 和 org.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 介面的實作,在獨立的應用程式中,常見的實體化方式是創建 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext 的一個實體,
不過,在我們日常的開發和作業中,我們基本上不需要顯式地去實體化一個或多個 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 之后,有一個完整配置的、可用的應用程式,

什么是配置元資料?
先說個結論,目前日常作業中,配置元資料基本都是以 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> 元素(或者說標簽),該元素有兩個屬性,id 和 class:
-
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 物件就是這個容器了,

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

接著,在 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.xml 和 services.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);
輸出:

總結
以上,就是本文的所有內容,主要講了什么是 Spring IoC 容器,介紹了 BeanFactory 和 ApplicationContext,
實際上這個 ApplicationContext 就代表容器,它會讀取我們的配置元資料,這樣它就知道該去管理哪些物件了,
也介紹了什么是 Bean,實際上就是被容器管理的物件,都是所謂的 Bean,也習慣稱為 Bean 物件,
還介紹了 Spring IoC 容器從頂層上來看是怎樣運行的,就是將各種業務物件和配置元資料相結合,組成一個完整配置的、可用的應用程式,
對于配置元資料,這個可以有多種形式,可以是 XML,可以是 Java 注解,可以是 Java 代碼,
最后就介紹了如何去實體化并使用 Spring IoC 容器,雖然我們日常開始是不會這樣去做的,不會去創建一個容器,然后通過容器的 getBean 去獲取 Bean 進行操作,但是我們就是需要了解學習,因為這些就是 Spring 的基礎,
最后的最后
希望各位螢屏前的靚仔靚女們給個三連!你輕輕地點了個贊,那將在我的心里世界增添一顆明亮而耀眼的星!
咱們下期再見!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554219.html
標籤:其他
下一篇:返回列表
