控制反轉
Spring IoC
的IoC
全稱是"Inversion of Control",譯:控制反轉數據結構
"控制反轉"又稱"依賴反轉"編碼
DI
全稱是"Dependency Injection",譯:依賴注入設計
使用控制反轉,依賴注入後,當建立對象時,由一個調度系統將其所依賴的對象的引用傳遞給它(這些對象也都來自於調度系統所管理的對象),即依賴被注入到對象中。因此,控制反轉是關於一個對象如何獲取它所依賴的對象的引用code
上述的調度系統是應用平臺,具體來講是IoC
容器。經過使用IoC
容器,對象依賴關係的管理被反轉了,轉到IoC
容器中來了,對象之間的相互依賴關係由IoC
容器進行管理,並由IoC
容器完成對象的注入xml
IoC容器的核心數據結構
BeanDefinition
是IoC
容器的核心數據結構。又稱"Bean定義信息"。是建立Bean
實例時所使用的模板對象
Bean
是容器管理的對象的統稱blog
容器在建立Bean
實例以前會先建立BeanDefinition
對象,它保存了Bean
的定義信息,例如Bean
的名字,類型,是單實例仍是多實例,是否是懶加載,所依賴的其餘對象有哪些等接口
IoC容器的設計與實現
IoC
容器有兩個系列生命週期
一個是實現BeanFactory
接口的簡單容器系列,這個系列的容器能實現容器的最基本的功能。又稱"Bean工廠"事件
一個是實現ApplicationContext
接口的高級容器系列,它是容器的高級形態。又稱"應用上下文"或"上下文"。上下文在簡單容器的基礎上又增長了許多新功能
Spring IoC容器的設計
下面這張圖描述的IoC
容器的接口設計圖,IoC
容器的實現類就是以容器的接口設計爲基礎實現的
設計主線
- 以
BeanFactory
爲核心。從BeanFactory
到HierarchicalBeanFactory
再到ConfigurableBeanFactory
。這是一條主要的BeanFactory
類型容器的設計路線 - 以
ApplicationContext
爲核心。從BeanFactory
到ListableBeanFactory
到ApplicationContext
,再到ConfigurableApplicationContext
或WebApplicationContext
。咱們經常使用的上下文基本都是ConfigurableApplicationContext
或WebApplicationContext
的實現類
咱們經常使用的BeanFactory
的實現類是DefaultListableBeanFactory
。同時,以這個實現類爲基礎,又有許多應用於不一樣場景下的子類bean工廠。不過咱們一般直接使用DefaultListableBeanFactory
咱們經常使用的ApplicationContext
的實現類是AbstractApplicationContext
的子類。這個抽象類包含了容器的初始化方法refresh()
。
AbstractApplicationContext
實現的是ConfigurableApplicationContext
接口。
BeanFactory的設計原理
這些接口方法定義出了一個基本的IoC
容器
boolean containsBean(String name);
容器中是否有名爲name
的Bean
String[] getAliases(String name);
查詢Bean
的全部別名getBean()
有多個重載方法,是從容器中獲取Bean
實例的方法(此方法包含若是獲取不到就建立一個Bean
實例的流程)boolean isSingleton(String name);
返回Bean
是不是單實例boolean isPrototype(String name)
返回Bean
是不是多實例(Bean
是單實例仍是多實例,這些信息保存在對應的BeanDefinition
對象中)- ...
這些方法提供了容器最基本的功能
ApplicationContext的設計原理
ApplicationContext
除了實現了BeanFactory
外還實現了其餘接口,爲容器添加了其餘功能
MessageSource
信息源。支持國際化功能的實現ResourceLoader
訪問資源。用於獲取Bean
的定義信息所在的資源,爲建立BeanDefinition
對象作準備ApplicationEventPublisher
發佈事件。能夠在上下文中,在Bean
的生命週期中發佈事件- ...
容器初始化流程
首先,由編碼者使用某種形式編寫Bean
的配置信息,例如在.xml文件中寫<bean>
標籤配置Bean
而後,啓動容器進行初始化。容器初始化大體分三步
BeanDefinition
的Resource
定位(定位Bean
配置信息所在位置)- 載入
BeanDefinition
(建立BeanDefinition
對象) - 向容器註冊
BeanDefinition
對象(在容器內部將對象put到一個容器持有的map對象中)
在第一次調用容器的getBean()
方法(BeanFactory
中定義的方法)獲取Bean
對象時,若是對象還未被實例化,就獲取對應的BeanDefinition
對象,並使用它做爲模板建立實例對象
再容器完成初始化後,調用refresh()
方法刷新容器。方法執行完後容器即可以使用
ps:容器初始化的流程可能在refresh()
方法外執行,也可能在refresh()
方法內執行