spring IOC源碼分析(1)

1.何謂Spring IOC

        何謂Spring IOC?書上謂之“依賴注入”,那何謂“依賴注入”?

        作爲一個Java程序猿,應該遇到過這樣的問題,當你在代碼中需要使用某個類提供的功能時,你首先需要new一個對象,給它傳遞必要的參數,然後才能使用它提供的功能,最後釋放對象佔用的內存,當然了這個在Java不需要你自己去幹了。這也就是說你需要自己去管理變量的整個生命週期,這在大型項目中是很糟糕的。現在好了,有了Spring IOC,這些事情都不需要你去做,你只需要告訴Spring你需要的變量實例,配置其對應關係,Spring就可以講你依賴的實例注入到你的變量中。

        舉個現實的例子,在以前大家找對象都是自己去找,自己去處的,現在不一樣了,很多人都通過相親了,這就有了相親機構,其實這裏相親機構就是一個Spring IOC容器,你想要找對象,然後你就去找相親機構,在它那裏注個冊,告訴它你的要求,比如說高矮胖瘦等等,這個時候,相親機構就從已經在它那註冊了的所有女生中(注:這個時候,你跟那些女生都是相親機構管理的bean對象)找到符合你要求的女生,最後給到你,讓你們自己去折騰了……,這也就是所謂的“依賴注入”,也就是Spring IOC的精髓所在。

 

2 Spring IOC體系結構

 

Bean工廠

         SpringBean的創建是典型的工廠模式,這一系列的Bean工廠,也即IOC容器爲開發者管理對象間的依賴關係提供了很多便利和基礎服務,在Spring中有許多的IOC容器的實現供用戶選擇和使用,其相互關係如下:


        其中BeanFactory作爲最頂層的一個接口類,它定義了IOC容器的基本功能規範,BeanFactory 有三個子類:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。但是從上圖中我們可以發現最終的默認實現類是 DefaultListableBeanFactory,他實現了所有的接口。那爲何要定義這麼多層次的接口呢?查閱這些接口的源碼和說明發現,每個接口都有他使用的場合,它主要是爲了區分在 Spring 內部在操作過程中對象的傳遞和轉化過程中,對對象的數據訪問所做的限制。例如 ListableBeanFactory 接口表示這些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是這些 Bean 是有繼承關係的,也就是每個Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定義 Bean 的自動裝配規則。這四個接口共同定義了 Bean 的集合、Bean 之間的關係、以及 Bean 行爲。

 

Bean的表示

         SpringIOC容器管理了我們定義的各種Bean對象及其相互的關係,Bean對象在Spring實現中是以BeanDefinition來描述的,其繼承體系如下:


        Bean 的解析過程非常複雜,功能被分的很細,因爲這裏需要被擴展的地方很多,必須保證有足夠的靈活性,以應對可能的變化。Bean 的解析主要就是對 Spring 配置文件的解析。這個解析過程主要通過下圖中的類完成:



        

        

       2. 最基本的IOC容器接口:

       

1.	public interface BeanFactory {  
2.	  
3.	//這裏是對FactoryBean的轉義定義,因爲如果使用bean的名字檢索FactoryBean得到的對象是工廠生成的對象,  
4.	//如果需要得到工廠本身,需要轉義         
5.	    String FACTORY_BEAN_PREFIX = "&";  
6.	  
7.	  
8.	//這裏根據bean的名字,在IOC容器中得到bean實例,這個IOC容器就是一個大的抽象工廠。  
9.	    Object getBean(String name) throws BeansException;  
10.	  
11.	//這裏根據bean的名字和Class類型來得到bean實例,和上面的方法不同在於它會拋出異常:如果根據名字取得的bean實例的Class類型和需要的不同的話。  
12.	    Object getBean(String name, Class requiredType) throws BeansException;  
13.	  
14.	//這裏提供對bean的檢索,看看是否在IOC容器有這個名字的bean  
15.	    boolean containsBean(String name);  
16.	  
17.	    //這裏根據bean名字得到bean實例,並同時判斷這個bean是不是單件  
18.	    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  
19.	  
20.	    //這裏對得到bean實例的Class類型  
21.	    Class getType(String name) throws NoSuchBeanDefinitionException;  
22.	  
23.	    //這裏得到bean的別名,如果根據別名檢索,那麼其原名也會被檢索出來  
24.	    String[] getAliases(String name);  
25.	  
26.	} 

         在BeanFactory裏只對IOC容器的基本行爲作了定義,根本不關心你的bean是如何定義怎樣加載的。正如我們只關心工廠裏得到什麼的產品對象,至於工廠是怎麼生產這些對象的,這個基本的接口不關心。

         而要知道工廠是如何產生對象的,我們需要看具體的IOC容器實現,spring提供了許多IOC容器的實現。比如XmlBeanFactory,ClasspathXmlApplicationContext等。


3.    IoC容器的初始化

       

        IoC容器的初始化包括BeanDefinition的Resource定位、載入和註冊這三個基本的過程。我們以ApplicationContext爲例講解,ApplicationContext系列容器也許是我們最熟悉的,因爲web項目中使用的XmlWebApplicationContext就屬於這個繼承體系,還有ClasspathXmlApplicationContext等,其繼承體系如下圖所示:



         ApplicationContext允許上下文嵌套,通過保持父上下文可以維持一個上下文體系。對於bean的查找可以在這個上下文體系中發生,首先檢查當前上下文,其次是父上下文,逐級向上,這樣爲不同的Spring應用提供了一個共享的bean定義環境。


         從ApplicationContext接口的實現,我們看出其特點:

         1.  支持信息源,可以實現國際化。(實現MessageSource接口)

         2.  訪問資源。(實現ResourcePatternResolver接口,這個後面要講)

         3.  支持應用事件。(實現ApplicationEventPublisher接口)


         我們看ClassPathXmlApplicationContext是如何建立IOC容器,先看其構造函數:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

         refresh的模板是在AbstractApplicationContext中:

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}
			……
這裏是我們分析的入口,其完成了整個的bean初始化過程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章