Spring IOC源碼分析(3)

1.IOC容器的依賴注入

        Spring中,依賴注入是在用戶第一次向IOC容器索要Bean時觸發的(通過getBean方法)。

       在BeanFactory中我們看到getBean(String…)函數,它的具體實現在AbstractBeanFactory中:

public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
}

        可以看到具體的注入過程轉移到doGetBean(String…)中,在這個方法中,它首先從緩存中取,如果單件模式的bean已經被創建,則這種bean請求不需要重複的創建,調用

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

        跟蹤進入getObjectForBeanInstance(…,null),可以知道因爲最後的RootBeanDefinition參數是null,所以執行的是:

if (mbd == null) {
	object = getCachedObjectForFactoryBean(beanName);
}

        而getCachedObjectForFactoryBean(beanName)中實現,其實現很簡單,就是在緩存的bean map中查找bean返回。

        繼續回到doGetBean(String…)方法中:

         //取當前bean的所有依賴bean,這樣就會觸發getBean的遞歸調用,直至取到一個沒有任何依賴的bean爲止
	String[] dependsOn = mbd.getDependsOn();
	if (dependsOn != null) {
		for (String dependsOnBean : dependsOn) {
			getBean(dependsOnBean);
	                  //註冊依賴的bean實例,具體實現過程在DefaultSingletonBeanRegistry中實現,其實就是將依賴的bean添加到依賴的hashmap中
			registerDependentBean(dependsOnBean, beanName);
		}
	}
	//通過調用createBean來,創建單例bean的實例
	if (mbd.isSingleton()) {
		sharedInstance = getSingleton(beanName, new ObjectFactory() {
		   public Object getObject() throws BeansException {
		     try {
			  return createBean(beanName, mbd, args);
		     }
		     catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		     }
	            }
	        });
	        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}
	//同樣調用createBean創建prototype的bean實例
	else if (mbd.isPrototype()) {
		// It's a prototype -> create a new instance.
		Object prototypeInstance = null;
		try {
			beforePrototypeCreation(beanName);
			prototypeInstance = createBean(beanName, mbd, args);
		}
		finally {
			afterPrototypeCreation(beanName);
		}
        bean=getObjectForBeanInstance(prototypeInstance,name, beanName, mbd);
}

        繼續看createBean(…),可以看到在AbstractBeanFactory中它只是個抽象類,具體的實現交給其子類(又見模板模式),進入子類AbstractAutowireCapableBeanFactory中看createBean的具體實現:

Object beanInstance = doCreateBean(beanName, mbd, args);


        其具體的實現轉到doCreateBean(String…),這裏我們看到與依賴注入關係比較密切的方法有createBeanInstance和populateBean。

BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
	instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
	instanceWrapper = createBeanInstance(beanName, mbd, args);
}


// Initialize the bean instance.
Object exposedObject = bean;
try {
	populateBean(beanName, mbd, instanceWrapper);
	if (exposedObject != null) {
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
}

        在createBeanInstance中生成了Bean所包含的Java對象,這個對象的生成有很多不同的方式,可以通過工廠方法生成,也可以通過容器的autowire特性生成,生成的方式由相關聯的BeanDefinition來指定,進入createBeanInstance方法,有:

return instantiateUsingFactoryMethod(beanName, mbd, args);


return instantiateBean(beanName, mbd);


        上面是其中的兩個實例化方法,上面的是在BeanDefinition的FactoryMethod存在的情況下,使用工廠方法對bean進行實例化。下面一個是使用默認的構造函數對bean進行實例化。我們進入instantiateBean(beanName,mbd),可以看到有:

return getInstantiationStrategy().instantiate(mbd, beanName, parent);


        因爲getInstantiationStrategy()返回的默認的實例化策略,而默認的實例化策略是CglibSubclassingInstantiationStrategy,也即用cglib來對bean進行實例化。CGLIB是一個常用的字節碼生成器的類庫,它提供了一系列的API來提供Java的字節碼生成和轉換功能。

        我們再次回到doCreateBean()中的populateBean方法,看看在實例化Bean對象生成的基礎上,spring怎樣把這些bean對象的依賴關係設置好,完成整個依賴注入過程。在populateBean中,先是取得在BeanDefinition中設置的property值,這些property來自對BeanDefinition的解析,接着便開始進行依賴注入過程:

//開始進行依賴注入過程,先處理autowire的注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			//根據bean的名字進行autowire過程
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}

			//根據類型type進行autowire的過程
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
}

         最後在通過applyPropertyValues對屬性進行注入:

applyPropertyValues(beanName, mbd, bw, pvs);


         接着我們到applyPropertyValues中去看具體的對屬性進行解析然後注入的過程,在其中會調用BeanDefinitionValueResolver對BeanDefinition進行解析,


BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);


         接着爲解析值創建一個拷貝,拷貝的數據將會被注入到bean中,它會先對PropertyValue判斷,如果其沒有經過轉換則會調用resolveValueIfNecessary進行解析,然後注入到property中。下面到BeanDefinitionValueResolver中去看一下解析過程的實現,在函數resolveValueIfNecessary中包含了所有對注入類型的處理,以RuntimeBeanReference(其是在對BeanDefinition進行解析時生成的數據對象)爲例:


if (value instanceof RuntimeBeanReference) {
	RuntimeBeanReference ref = (RuntimeBeanReference) value;
	return resolveReference(argName, ref);
}
//當注入類型爲RuntimeBeanReference時,進入resolveReference(…):
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
		try {
			//從RuntimeBeanReference取得reference的名字
			String refName = ref.getBeanName();
			refName = String.valueOf(evaluate(refName));
			//如果ref是在雙親的IOC容器中,那就到雙親IOC容器中去取
			if (ref.isToParent()) {
				if (this.beanFactory.getParentBeanFactory() == null) {
					//拋出異常BeanCreationException
                                             ……
				}
				return this.beanFactory.getParentBeanFactory().
                                     getBean(refName);
			}
			else {
                                    //在當前IOC容器中去取bean
				Object bean = this.beanFactory.getBean(refName);
	                            this.beanFactory.registerDependentBean(refName, this.beanName);
				return bean;
			}
}

        在上面的實現中,無論是到雙親的IOC容器中去取,還是在當前IOC容器中取,都會觸發一個getBean的過程,這就觸發了相應的依賴注入的發生。

 

        這就完成了resolve的過程,爲依賴注入準備好了條件。但真正的把Bean對象設置到它所依賴的另一個Bean的屬性中去的地方是在BeanWrapper的setPropertyValues中(在分析populateBean的時候有提到),其中處理的屬性是各種各樣的。setPropertyValues的具體實現是在BeanWrapper的子類BeanWrapperImpl中:

        在doCreateBean中執行完populateBean,完成Bean的生成和依賴注入以後,開始對Bean進行初始化,這個初始化過程包含了對後置處理器的postProcessBeforeInitializtion回調,具體實現在initializeBean方法中:

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
	wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
	invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
	//拋出異常BeanCreationException
}

if (mbd == null || !mbd.isSynthetic()) {
	wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;




 



 

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