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;