第一節講解Spring啓動的時候說到,Spring內部先解析了全部的配置,加載全部的Bean定義後,再根據須要對Bean進行實例化和初始化。除開Spring本身主動新建的對象,第一次根據Bean定義加載對象的動做出如今AbstractApplicationContext的invokeBeanFactoryPostProcessors方法,該方法會在Spring容器中找出實現了BeanFactoryPostProcessor接口的bean列表並執行。根據以前介紹的內容,內部主要調用了AbstractBeanFactory的getBean方法,這節將對該方法進行講解。html
在這以前,先介紹BeanFactory的層次結構,以下:緩存
涉及到的接口和實現類爲:ide
AliasRegistry:別名管理接口,定義了別名管理的功能post
SimpleAliasRegistry:AliasRegistry的默認實現,內部用一個ui
ConcurrentHashMap:管理別名this
SingletonBeanRegistry:單例實例管理接口,定義了單例管理的功能spa
DefaultSingletonBeanRegistry:單例管理實現類,內部用Map維護着被實例化後的全部單例、單例工廠等相關信息。Map的鍵爲bean的惟一標識,Spring內部成爲raw name,通常等同於Bean定義中的id或者name或者別名等,具體規則能夠從上節BeanDefinition的加載查看,值爲相應的對象實例。這邊須要指出的一點是,對於bean定義中具備別名意義的字段,如必定狀況下的name以及alias字段,只存在於SimpleAliasRegistry維護的內部Map中,經過遞歸查詢的方式能夠從一個給定的別名查找到指定的id。prototype
以下,DefaultSingletonBeanRegistry維護的Map中存在key爲testBean,value爲TestBean的對象,SimpleAliasRegistry維護的Map中存在Key爲testBeanAlias1,value爲testBean的記錄。當經過testBeanAlias1查找bean時,會先經過AliasRegistry查找到testBean,再從經過BeanRegistry查找到對應的Bean實例。線程
FactoryBeanRegistrySupport:增長緩存FactoryBean實例功能,DefaultSingleBeanRegistry在生成單例後便再也不持有對應的FactoryBeandebug
BeanFactory:定義了Bean容器的基本查詢接口,同時設定了以&前綴來區別工廠Bean,即若是beanName前面有&則返回對應Bean的工廠Bean對象而不是該Bean對象。
HierarchicalBeanFactory:在BeanFactory接口上增長了父子層級關係,以實現雙親委託。
ConfigurableBeanFactory:按照規矩,增長了修改功能的接口,同時增長了Scope特性,默認分爲single單例和prototype多例。
AbstractBeanFactory:BeanFacoty的基本實現。
AbstractBeanFactory的getBean方法內部調用了doGetBean,該方法提供了根據beanName獲取實例的具體實現,代碼以下(刪除了相關的註釋和空格):
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { /*(1)*/ final String beanName = transformedBeanName(name); Object bean; /*(2)*/ Object sharedInstance = getSingleton(beanName); /*(3)*/ if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } /*(4)*/ else { /*(5)*/ if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } /*(6)*/ BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } /*(7)*/ if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { /*(8)*/ final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); /*(9)*/ String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } /*(10)*/ if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } /*(11)*/ else if (mbd.isPrototype()) { Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } /*(12)*/ else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { 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", ex); } } } catch (BeansException ex) { /*(13)*/ cleanupAfterBeanCreationFailure(beanName); throw ex; } } if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
先說下入參:
name:要查找的bean名,能夠爲raw name,也能夠爲alias name或者factoryBean name,Spring內部會自行進行轉換。
requiredType:要返回的對象類型
args:對象實例化時須要用到的構造參數
typeCheckOnly:該對象只是用來進行類型檢查,而不會真正的進行使用,能夠避免實例化和初始化對象
具體過程爲:
1.獲取raw name
計算所給name對應的內部beanName,具體爲循環去除name前面的&,再根據以前的介紹的,若是傳入的是別名,會查找到對應的raw name
2.嘗試獲取bean實例
使用上面得到的beanName,調用內部的getSingleton方法,獲取對應的對象實例,賦值給sharedInstance。getSingleton方法來自於DefaultSingletonBeanRegistry,即這步嘗試直接從內部維護的單例Map中獲取實例。這步能夠檢測到手工注入的singleton,如第一節提到的ApplicationContext對象,就是Spring本身手動註冊的。
3.bean實例已經存在
若sharedInstance不爲空,且args參數爲空,說明該對象已經存在,不須要再進行實例化和初始化。因爲在(1)的時候對所傳的name去除了&,須要判斷返回的對象是否符合要求。這時候,會使用getObjectForBeanInstance方法,對sharedInstance和name進行判斷,返回對應的實例,該方法主要內容以下:
若name以&開頭,但sharedInstance沒有實現FactoryBean接口,則拋出異常
若sharedInstance沒有實現FactoryBean接口,或者name以&開頭,則直接將sharedInstance對象返回。即sharedInstace自己是從name對應的FactoryBean獲取的對象。
若前面2個條件都不符合,則sharedInstance自己實現了FactoryBean接口,name也是以&開頭,這時候會嘗試從FactoryBeanRegistrySupport中根據beanName(raw name)獲取已經實例化的對象。若對象爲空,即首次獲取,則將sharedInstace轉爲FactoryBean,並調用該工廠方法獲取對象。這裏涉及到FactoryBeanRegistrySupport的getObjectFromFactoryBean方法,該方法在使用FactoryBean得到對象後,會調用上下文中已有的BeanPostProcessor對象列表,逐個執行postProcessAfterInitialization方法,當遇處處理後的結果爲空,則直接返回,不然繼續遍歷執行,以下,出如今AbstractAutowireCapableBeanFactory中:
4.Bean實例不存在
若是沒有找到beanName對應的實例,即不存在對應的單例實例,則轉入實例化該對象的流程,注意單例或者多例都須要實例化。
5.若是該beanName有對應的在初始化中的多例對象,則拋出異常。
AbstractBeanFactory內部維護了一個ThreadLocal對象,用於維護當前線程正在初始化的多例對象。
6.啓用雙親委託機制
若是存在父容器,且父容器存在該beanName的定義,則委託給父容器完成。
7.若是本次調用不單是爲了類型檢查,則標記該beanName在建立中
AbstractBeanFactory內部維護了一個Set<String>集合alreadyCreated,用於存儲已經建立好或者正在建立的bean
8.獲取該beanName對應的BeanDefinition,包裝爲RootBeanDefinition返回。
AbstractBeanFactory內部維護了一個Map<String, RootBeanDefinition>集合mergedBeanDefinitions,用於維護當前已經加載的各個bean定義bd。在加載該bean定義時,若是存在父定義pdb,則會將pdb包裝爲一個RootBeanDefinition,而後將當前的bd覆蓋掉父定義的內容,包括scope、lazyInit、dependsOn等屬性,達到繼承的效果。得到RootBeanDefinition後,若是最後的定義中scope爲空,則會默認賦值爲single。此外還有一個containingBd的概念,這個是相對於bd來講的,指的是包含bd的外部bean定義,主要用於inner bean的狀況。若是包含containingBd不爲空,且不是單例,可是bd爲單例,則bd的scope須要設置爲containingBd的值,直白點說就是包含被非單例bean包含的bean自己不能爲單例(這段有點繞,還沒找到實際的例子,直接按照代碼裏的直譯過來)。
9.處理依賴的bean
獲取該bean依賴的bean列表dependsOn值,對每一個依賴的bean進行逐一操做,先檢查該bean是否存在循環依賴,若不存在循環依賴,則將依賴關係緩存起來,最後先實例化依賴的bean。其中檢查循環依賴很重要,若是沒有該步,最後實例化依賴的bean時會致使死循環。爲此AbstractBeanFacotry內部維護了兩個Map<String, Set<String>>屬性dependentBeanMap和dependenciesForBeanMap,分別用於緩存bean的依賴關係。前者表示bean從屬關係的緩存,緩存依賴於key所表示的bean的全部bean name,舉例來說,若是beanB的一個屬性是beanA,則beanA爲key是被依賴方,beanB則爲value是依賴方(從屬方)的一員;後者標識bean依賴關係的緩存,緩存key所表示的bean依賴的全部bean name,舉例來說,若是beanB的一個屬性是beanA,則beanB是key從屬方,beanA則是value被依賴方的一員。以下爲Spring檢查循環依賴的過程:
其中beanName爲當前bean,dependentBeanName爲當前bean所依賴的bean。大體過程爲找出全部依賴beanName的bean列表transitiveDependency,遞歸判斷transitiveDependency是否也依賴dependentBeanNam,即若是 beanName依賴於 dependentBeanName ,並且 transitiveDependency依賴於 beanName, 若是transitiveDependency 依賴於dependentBeanName,即出現了環,則存在循環依賴。
10.若是該bean爲單例,則轉入初始化單例流程
調用父類DefaultSingletonBeanRegistry的getSingleton模板方法,該模板方法會保證該單例只有被建立一次,建立完成後將對象緩存在內部。真正實例化和初始化的過程在createBean方法中,其中若是該bean實例化失敗,則會調用destroySingleton方法進行回收,這兩個方法在後面會進行重點講解。同第二步相似,獲取該對象後,會再調用getObjectForBeanInstance檢查FactoryBean。
11.若是該bean爲多例,則轉入初始化多例流程
第(5)步講過,內部有一個ThreadLocal,保證多例在當前線程建立時是惟一的,重點方法也是createBean。須要注意的是,若是是多例,建立失敗是不會進行回收的。
12.若是該bean爲其餘scope,則轉入對應的初始化流程
具體過程同(10)一致,只是調用的模板委託給了具體的Scope對象。
13.初始化失敗,則清理相關內容
將該beanName從alreadyCreated移除,標識該beanName還未建立。
createBean方法主要用於完成bean的實例化和初始化過程,該方法在AbstractFactory中爲抽象方法,具體實現是在AbstractAutowireCapableBeanFactory類中。以下爲核心操做:
1.resolveBeforeInstantiation
建立對象前的代理口子,可以攔截建立過程,使用自定義的代理對象來替換Spring內部正常建立的對象,即上面判斷的,若是該方法返回對象不爲空,則直接使用返回的對象返回。實現上, 會逐一遍歷全部的BeanPostProcessor,找出InstantiationAwareBeanPostProcessor對象,並執行postProcessBeforeInstantiation方法,若返回結果不爲空,則直接使用該方法返回,以下:
該方法主要用在AOP實現上,上節提到的CommonAnnotationBeanPostProcessor和PersistenceAnnotationBeanPostProcessor類雖然實現了該接口,可是postProcessBeforeInstantiation方法爲空實現。
若該方法返回對象不爲空,則會逐一執行BeanPostProcessor列表的postProcessAfterInitialization方法,以完成回調。
2.doCreateBean
該方法的主要過程以下,省略了提早暴露bean實例的部份內容。
由上圖可知,該過程完成了bean的實例化和初始化以及調用各回調接口的過程。具體爲:
主要嘗試從各類方法進行實例化,包括:
a. 使用工廠方法進行實例化
b. 使用bean定義的構造方法或者可用的構造方法進行實例化
c. 使用默認的構造方法進行實例化
以下,遍歷各個MergedBeanDefinitionPostProcessor實例,回調postProcessMergedBeanDefinition方法
3.初始化對象,填充各屬性
執行初始化,實現屬性的依賴注入,在自動進行依賴注入前, 會先調用一個回調接口,以判斷是否須要自動依賴注入,以下:
經過回調InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法來判斷。
若須要進行依賴注入,則會根據依賴策略:根據autowireByName或者autowireByType,爲屬性字段找到符合定義的bean實例(會經過getBean方法調用)。在真正將值賦值給屬性前, 還會再次執行回調接口,以下,回調InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法,這裏也能夠進行攔截。
若前面都沒被攔截到,則會真正將bean值複製給對應的屬性,最終會經過反射設置field的accessable,而後將bean實例設置進去。
4.執行各回調接口
執行Aware接口,包括BeanNameAware、BeanClassLoaderAware和BeanFactoryAware
若是該Bean實現了InitializingBean接口,則調用afterPropertiesSet方法
若是設置了init-method,則執行init-method指定的方法
執行BeanPostProcessor的postProcessAfterInitialization方法
5.判斷是否有銷燬接口,並添加到列表中
以下,爲處理過程,會先判斷當前bean定義不是多例,且須要進行銷燬回調,纔會進行處理。若是是單例,則直接將其添加到響應列表列表中進行緩存,存儲在內部維護的disposableBeans列表中;若是是其餘socpe,則將其委託給對應的Scope對象實現。
這裏有幾個條件:
必須爲非prototy
該bean存在銷燬方法,知足一下條件之一便是
a. 該bean實現了DisposableBean接口
b. 該bean實現了AutoCloseable接口
c.該bean實現了Closeable接口
d.該bean定義的destory-method不爲空
e.該bean符合DestructionAwareBeanPostProcessor.requiresDestruction方法的過濾條件
只要符合以上條件,就會新建一個DisposableBeanAdapter對象進行存儲,並在銷燬時進行相應的接口回調。
結合以前幾節內容,能夠獲得以下的回調順序:
以上爲大體的過程,不含其它的回調接口,如有其它回調接口能夠按照順序依次加入。
我的公衆號:啊駝
原文出處:https://www.cnblogs.com/cxyAtuo/p/11626648.html