1. 程式人生 > 實用技巧 >bean的建立過程--doGetBean

bean的建立過程--doGetBean

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
        //處理別名,提取對應的beanName
        final String beanName = this.transformedBeanName(name);
        /**
         * 檢查快取中或者例項工廠中是否有對應的例項
         * 為什麼會首先使用這段程式碼呢?
         * 因為在建立單例bean的時候會存在依賴注入的情況,而在建立依賴的時候為了避免迴圈依賴
         * Spring建立bean的原則是不等bean建立完就會將建立bean的ObjectFactory提早曝光,也就是將ObjectFactory加入到快取中,一旦下個bean建立時候需要依賴上個bean則直接使用ObjectFactory
         
*/ //直接嘗試從快取獲取或者singletonFactories中的ObjectFactory中獲取 Object sharedInstance = this.getSingleton(beanName); Object bean; if (sharedInstance != null && args == null) { if (this.logger.isDebugEnabled()) { if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } }
//返回對應的例項,有時候存在諸如BeanFactory的情況並不是直接返回例項本身而是返回指定方法返回的例項 bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); } else { //只有在單例情況下才會嘗試解決迴圈依賴,如果是原型模式下 則直接丟擲如下異常 if (this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = this.getParentBeanFactory(); //如果beanDefinitionMap中也就是所有已經載入的類中不包括beanname則嘗試從parentBeanFactory中檢測 if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) { String nameToLookup = this.originalBeanName(name); //遞迴到BeanFactory中尋找 if (args != null) { return parentBeanFactory.getBean(nameToLookup, args); } return parentBeanFactory.getBean(nameToLookup, requiredType); } if (!typeCheckOnly) { this.markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); this.checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); String[] var11; //若存在依賴則需要遞迴例項化依賴的bean if (dependsOn != null) { var11 = dependsOn; int var12 = dependsOn.length; for(int var13 = 0; var13 < var12; ++var13) { String dependsOnBean = var11[var13]; if (this.isDependent(beanName, dependsOnBean)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'"); } //快取依賴呼叫 this.registerDependentBean(dependsOnBean, beanName); this.getBean(dependsOnBean); } } //例項化依賴的bean後便可以例項化mbd本身 //singleton模式的建立 if (mbd.isSingleton()) { sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return AbstractBeanFactory.this.createBean(beanName, mbd, args); } catch (BeansException var2) { AbstractBeanFactory.this.destroySingleton(beanName); throw var2; } } }); bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { //protoType模式的建立 var11 = null; Object prototypeInstance; try { this.beforePrototypeCreation(beanName); prototypeInstance = this.createBean(beanName, mbd, args); } finally { this.afterPrototypeCreation(beanName); } bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { //指定的scope上例項化bean String scopeName = mbd.getScope(); Scope scope = (Scope)this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { AbstractBeanFactory.this.beforePrototypeCreation(beanName); Object var1; try { var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args); } finally { AbstractBeanFactory.this.afterPrototypeCreation(beanName); } return var1; } }); bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException var21) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var21); } } } catch (BeansException var23) { this.cleanupAfterBeanCreationFailure(beanName); throw var23; } } //檢查需要的型別是否符合bean的實際型別 if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return this.getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException var22) { if (this.logger.isDebugEnabled()) { this.logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", var22); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } else { return bean; } }

從上述程式碼可以看出bean的載入經歷了一個複雜的過程,以上僅能粗略的瞭解整個Spring載入bean的過程。載入的步驟大致如下

1:轉換對應的beanName

因為傳入的引數不僅是beanName也可能是別名,也可能是FactoryBean,所以需要解析:去除FactoryBean的修飾符,也就是如果name="&aa",那麼會首先去除&而使name="aa"。

取指定alias所表示的最終beanName,例如別名A指向名稱B的bean則返回B;

2:嘗試從快取中載入單例

單例在spring容器內只會建立一次,後續獲取都是從單例快取中獲取。如果獲取不到則從singletonFactories中載入。因為在建立單例bean的時候會存在依賴注入的情況,而在建立的時候為了

避免迴圈依賴,在Spring中建立bean的原則是不等bean建立完就會將建立bean的ObjectFactory提早曝光,也就是將ObjectFactory加入到快取中,一旦下個bean建立時候需要依賴上個bean則直接使用ObjectFactory

3:bean的例項化

如果從快取中得到了bean的原始狀態,則需要對bean進行例項化。

4:原型模式的依賴檢查

只有在單例情況下才會嘗試解決迴圈依賴

5:加測parentBeanFactory

如果快取中沒有取到則直接轉到父類工廠上載入。

6:將儲存xml配置檔案的GernericBeanDefinition轉換為RootBeanDefinition

7:尋找依賴

8:針對不同的scope進行bean的建立

9:型別轉換

快取池獲取bean例項

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //一級快取:存放的是已經完成例項化,屬性填充和初始化步驟的單例bean例項
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        synchronized(this.singletonObjects) {
            //二級快取:存放的是提前暴露的單例bean例項,可能是代理物件,也可能是未經代理的原物件,但都還沒有完成初始化的步驟
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                //三級快取:存放的是ObjectFactory的匿名內部類例項
                ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //回撥ObjectFactory#getObject方法獲取提前暴露的引用
                    singletonObject = singletonFactory.getObject();
                    //移入二級快取
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    //移除三級快取
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject != NULL_OBJECT ? singletonObject : null;
}