Spring框架的本質:2Spring IoC其實很簡單

有部分開發者對IoC(Inversion Of Control)和DI(Dependency Injection)的概念有些混淆,認爲二者是對等的,實際上IoC有兩種方式,一種是DI,另一種是DL,即Dependency Lookup(依賴查找),前者是當前軟件實體被動接受其依賴的其它組件被IoC容器注入,而後者則是當前軟件實體主動去某個服務註冊地查找其依賴的那些服務,概念之間的關係如下圖所示可能更貼切些
在這裏插入圖片描述

我們通常提到的Spring IoC,實際上是指Spring框架提供的IoC容器實現(IoC Container),而使用Spring IoC容器的一個經典代碼片段就是:

public App{
	public static void main(String [] args){
		ApplicationContext context=new FileSystemXmlApplication-Context("...");
		//...
		MockService Service = context.getBean(MockService.class);
		service.doSoomething();
	}
}

任何一個使用spring框架構建的獨立的Java應用(Standalone Java Application),通常會存在一行類似於“context.getBean(…);”的代碼,實際上,這行代碼做的就是DL的工作,而構建任何一種IoC容器的背後(比如BeanFactory或者ApplicationContext)發生的事情,則是更多的DI的過程(也有可能有部分DL的邏輯用於對接遺留系統)。

Spring的IoC容器中發生的事情其實也很簡單,總結下來即兩個階段:

  1. 採摘和蒐集“咖啡豆”
  2. 研磨和烹飪咖啡

哦,不對,這是技術討論,差點變成討論咖啡文化。那我們還是回過頭來繼續說Spring IoC容器的依賴注入流程吧!Spring IoC 容器的依賴注入工作可以分爲兩個階段:

  • 階段一:收集和註冊
    第一個階段可以認爲是構建和收集Bean定義的階段,在這個階段中,我們可以通過XML或者Java代碼的方式定義一些Bean,然後通過手動組裝或者讓容器基於某些機制自動掃描的形式,將這些bean定義收集到IoC容器中。
    假設我們以XML配置的形式來收集並註冊一bean,一般形式如下:

    	<bean id="mockService" class="..MockServiceImpl">
    	...
    	</bean>
    

    如果逐個收集bean定義麻煩,想批量收集並註冊到IoC容器中,我們也可以通過XML Schema形式的配置進行批量掃描並採集和註冊:

    	<context:component-scan base-package="com.cafe">
    

    注意:基於JavaConfig形式的收集和註冊,不管是單一還是批量,後面我們都會單獨提交。

  • 階段二:分析和組裝
    當第一階段工作完成後,我們可以先暫且認爲IoC容器中充斥着一個個獨立的bean,它們之間沒有任何關係。但實際上,它們之間是有依賴關係的,所以,IoC容器在第二階段要乾的事情就是分析這些已經在IoC容器之中的bean,然後根據它們之間的依賴關係先後組裝它們。如果IoC容器發現某個bean依賴另一個bean,它就會將這另一個bean注入給依賴它的那個bean,直到所有bean的依賴都注入完成,所有bean都“整裝待發”,整個IoC容器的工作即算完成。
    至於分析和組裝的依據,Spring框架最早是通過XML配置文件的形式來描述bean與bean之間的關係的,隨着Java業界研發技術和理念的轉變,基於Java代碼和Annotation元信息的描述方式日漸興盛(比如@Autowired和@Inject),但不管使用哪種方式,都只是爲了簡化綁定邏輯描述的各種“表象”,最終都是爲本階段的最終目的服務。
    tip:很多開發人員一定認爲spring的XML配置文件是一種配置(Configuration),但本質上,這些配置文件更應該是一種代碼形式,XML在這裏其實可以看做一種DSL,它用來表述的是bean和bean之間的依賴綁定關係,諸君還記得沒有IoC容器的年代要自己寫代碼新建(new)對象並配置(set)依賴的吧?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章