Q:談談你對Spring IoC的理解,它的實現原理是什么?
A:IoC,即控制反轉,它通過將控制權交給spring容器,來實現對象之間的解耦,減少了代碼修改的工作量。真實的例子來說,如果A類中有對B類的引用,那么A就有著對B的控制權,如果在代碼中直接創建B類對象的話,在B類需要更改時,A類也要隨之更改;IoC則是將控制權交給Spring容器,A類中不對B類對象進行初始化,在程序需要B類的時候,spring容器會為A類裝配B類對象,這樣,即使B類改變,A類也無需做出修改。
Spring IoC是基于工廠模式+反射技術實現的。實現的步驟如下:
配置文件中的每一個<bean>標簽即對應著一個BeanFactory對象,IoC容器在初始化階段會先構建一個工廠類,默認是DefaultListedBeanFactory,以下是BeanFactory類的UML圖:
它的三個子接口分別對應了三種不同的功能。
以上接口的實現類構成了工廠類的真正執行單元,也即是IoC容器,主要有兩個:XmlBeanFactory和ApplicationContext,由于前者功能太基礎,已經被廢棄,不建議使用,后者的子類UML圖如下:
三個最終的子類分別對應了加載配置文件的三個場景。
接下來是IoC容器的初始化過程:
BeanDefinitionReader通過讀取配置文件將其封裝到Resource類,之后通過XML解析器將為各個<bean>標簽生成對應的BeanDefinition對象,但是這里的BeanFactory還是各半成品,之后利用容器中注冊的BeanFatoryPostProcessor類將其加工成成品。
BeanDefinition加工完成之后,會被注冊到BeanDefinitionRegistry中去,后續操作直接從中拿取配置信息。
至此,初始化部分完成。
依賴注入:
在調用getBean()方法時,便開啟了Bean的生命周期,生命周期圖如下:
其中BeanNameAware類為該bean設置配置文件中設置的name,BeanFactoryAware為bean設置工廠名,這些都是bean生命周期中自帶的類。此類的類還有InitializingBean,DisposableBean。
而圖中標有?的類都不是生命周期自帶的,它們在配置文件中注冊,程序員可以根據自己的需求在實例化前后,以及初始化前后進行“后處理器”操作(AOP)。
Spring中支持5中bean的作用域:
作用域 | 解釋 |
---|---|
singleton | 該作用域將 bean 的定義的限制在每一個 Spring IoC 容器中的一個單一實例(默認)。 |
prototype | 該作用域將單一 bean 的定義限制在任意數量的對象實例。 |
request | 該作用域將 bean 的定義限制為 HTTP 請求。只在 web-aware Spring ApplicationContext 的上下文中有效。 |
session | 該作用域將 bean 的定義限制為 HTTP 會話。 只在web-aware Spring ApplicationContext的上下文中有效。 |
global-session | 該作用域將 bean 的定義限制為全局 HTTP 會話。只在 web-aware Spring ApplicationContext 的上下文中有效。 |
IoC依賴注入的三種方式:
- 構造函數注入:通過調用類的構造函數,將接口實現類通過構造函數變量傳入;
- 屬性注入:可以有選擇的通過setter方法完成調用類所需依賴的注入;
- 接口注入:將調用類所有依賴注入的方法抽取到一個接口中,調用類通過實現該接口提供的相應的注入方法,效果和屬性注入是完全一樣,但增加了類的數目,所以不提倡;