Spring源碼分析----IoC容器(二)

接着上一篇說,我們再看下refresh方法: 
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 這邊我們裝載了bean放到了map中 			
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 添加一些 Spring 本身需要的一些工具類
			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();
				// 上面部分是BeanPostProcessor的處理,相當於監聽器,可以對用戶的一些自定義功能進行處理。屬於bean擴展功能,有點aop的思想。
				// Instantiate all remaining (non-lazy-init) singletons.
				// 這邊對沒有延遲加載的bean進行實例化。
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}
 
 下面主要看看實例化bean的這個方法finishBeanFactoryInitialization(beanFactory):
	public void preInstantiateSingletons() throws BeansException {
		if (this.logger.isInfoEnabled()) {
			this.logger.info("Pre-instantiating singletons in " + this);
		}
		synchronized (this.beanDefinitionMap) {
			// Iterate over a copy to allow for init methods which in turn register new bean definitions.
			// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
			List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
			for (String beanName : beanNames) {
				RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
				if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
					if (isFactoryBean(beanName)) {
						final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
								public Boolean run() {
									return ((SmartFactoryBean) factory).isEagerInit();
								}
							}, getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
					else {
						getBean(beanName);
					}
				}
			}
		}
	}

 

 

 上面有個isFactoryBean()方法,判斷這個bean是否是屬於FactoryBean類型。我們spring中管理了兩種bean:普通的bean和工廠Bean(即實現了FactoryBean接口的bean),當一個受Spring容器管理的bean  如果實現了FactoryBean接口  在bean實例化(getBean)階段  Spring會調用該bean的getObejct方法,返回的不一定是自身的實例,若想獲得自身bean可以通過加個&符號的方式來獲得,如:context.getBean("&sayHelloFactoryBean");

bean實例化時序圖:

 

 

最終將bean實例化後的bean實例對象以Map的形式保存在DefaultSingletonBeanRegistry類中的singletonObjects對象中,以beanName爲key,實例化對象爲value。

 

bean對象依賴關係時序圖:




 

Ioc 容器的擴展點

現在還有一個問題就是如何讓這些 Bean 對象有一定的擴展性,就是可以加入用戶的一些操作。那麼有哪些擴展點呢? Spring 又是如何調用到這些擴展點的?

對 Spring 的 Ioc 容器來說,主要有這麼幾個。BeanFactoryPostProcessor, BeanPostProcessor。他們分別是在構建 BeanFactory 和構建 Bean 對象時調用。還有就是 InitializingBean 和 DisposableBean 他們分別是在 Bean 實例創建和銷燬時被調用。用戶可以實現這些接口中定義的方法,Spring 就會在適當的時候調用他們。還有一個是 FactoryBean 他是個特殊的 Bean,這個 Bean 可以被用戶更多的控制。

這些擴展點通常也是我們使用 Spring 來完成我們特定任務的地方,如何精通 Spring 就看你有沒有掌握好 Spring 有哪些擴展點,並且如何使用他們,要知道如何使用他們就必須瞭解他們內在的機理。可以用下面一個比喻來解釋。

我們把 Ioc 容器比作一個箱子,這個箱子裏有若干個球的模子,可以用這些模子來造很多種不同的球,還有一個造這些球模的機器,這個機器可以產生球模。那麼他們的對應關係就是 BeanFactory 就是那個造球模的機器,球模就是 Bean,而球模造出來的球就是 Bean 的實例。那前面所說的幾個擴展點又在什麼地方呢? BeanFactoryPostProcessor 對應到當造球模被造出來時,你將有機會可以對其做出設當的修正,也就是他可以幫你修改球模。而 InitializingBean 和 DisposableBean 是在球模造球的開始和結束階段,你可以完成一些預備和掃尾工作。BeanPostProcessor 就可以讓你對球模造出來的球做出適當的修正。最後還有一個 FactoryBean,它可是一個神奇的球模。這個球模不是預先就定型了,而是由你來給他確定它的形狀,既然你可以確定這個球模型的形狀,當然他造出來的球肯定就是你想要的球了,這樣在這個箱子里尼可以發現所有你想要的球

Ioc 容器如何爲我所用

前面的介紹了 Spring 容器的構建過程,那 Spring 能爲我們做什麼,Spring 的 Ioc 容器又能做什麼呢?我們使用 Spring 必須要首先構建 Ioc 容器,沒有它 Spring 無法工作,ApplicatonContext.xml 就是 Ioc 容器的默認配置文件,Spring 的所有特性功能都是基於這個 Ioc 容器工作的,比如後面要介紹的 AOP。

Ioc 它實際上就是爲你構建了一個魔方,Spring 爲你搭好了骨骼架構,這個魔方到底能變出什麼好的東西出來,這必須要有你的參與。那我們怎麼參與?這就是前面說的要了解 Spring 中那有些擴展點,我們通過實現那些擴展點來改變 Spring 的通用行爲。至於如何實現擴展點來得到我們想要的個性結果,Spring 中有很多例子,其中 AOP 的實現就是 Spring 本身實現了其擴展點來達到了它想要的特性功能,可以拿來參考。

 

參考:http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/#major2

 

 

發佈了117 篇原創文章 · 獲贊 9 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章