上文中咱們學習了bean加載的整個過程,咱們知道從spring容器中獲取單例bean時會先從緩存嘗試獲取,若是緩存中不存在已經加載的單例bean就須要從頭開始bean的建立,而bean的建立過程是很是複雜的,本文就開始研究bean加載這部分的源碼。html
在Spring中bean加載的邏輯是在getSingleton的重載方法中實現的:spring
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "'beanName' must not be null"); // 全局變量須要同步 synchronized (this.singletonObjects) { // 首先檢查對應的bean是否已經加載過,由於singleton模式就是複用已建立的bean,因此這一步是必須的 Object singletonObject = this.singletonObjects.get(beanName); // 若是爲空才能夠進行singleton的bean的初始化 if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while the singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<Exception>(); } try { // 初始化bean singletonObject = singletonFactory.getObject(); } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } // 加入緩存 addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
這裏建立bean使用了回調方法(實際上是匿名內部類),真正獲取單例bean的方法其實現邏輯是在ObjectFactory類型的實例singletonFactory的getObject()方法中實現的。Spring在建立單例先後還有一些準備及處理操做,包括以下內容:緩存
歸納起來主要有下面幾方面:架構
在beforeSingletonCreation()方法中有一個很重要的操做:記錄加載狀態,也就是經過this.singletonsCurrentlyInCreation.add(beanName)將當前正要建立的bean記錄在緩存中,這樣即可以對循環依賴進行檢測。app
protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.containsKey(beanName) && this.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != null) { throw new BeanCurrentlyInCreationException(beanName); } }
同記錄加載狀態類似,當bean加載結束後須要移除緩存中記錄的該bean的加載狀態記錄:ide
protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.containsKey(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } }
將結果記錄至緩存並刪除加載bean過程當中所記錄的各類輔助狀態:函數
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
雖然前面已經分析了加載bean的邏輯架構,但如今並無開始對bean加載功能的探索,前面提到過,bean加載邏輯實際上是在匿名內部類ObjectFactory的getObject()方法中定義的:post
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } } });
ObjectFactory的核心部分其實只是調用了createBean()方法,也就是建立的bean的邏輯都在這裏面,因此咱們還需繼續尋找真理。學習
跟蹤了這麼多Spring代碼,也發現了一些規律:一個真正幹活的函數實際上是以do開頭的,好比doGetObjectFromFactoryBean(),而容易給咱們帶來錯覺的函數,好比getObjectFromFactoryBean(),其實只是從全局角度作了一些統籌工做。這個規則對於createBean()也不例外,咱們就來看一下其中作了哪些準備工做:this
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } // 根據設置的class屬性或者根據className來解析Class resolveBeanClass(mbd, beanName); // 驗證及準備覆蓋的方法 try { mbd.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // 給BeanPostProcessors一個機會返回代理的機會來替代真正的實例 Object bean = resolveBeforeInstantiation(beanName, mbd); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } Object beanInstance = doCreateBean(beanName, mbd, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; }
總結一下具體步驟:
在Spring的配置裏面是沒有諸如override-method之類的配置,那爲何還須要有override屬性進行標記及驗證這一步呢?這是由於在Spring配置中存在lookup-method和replace-method的,而這兩個配置的加載其實就是將配置統一存放在BeadDefinition中的methodOverrides屬性裏,而這步操做就是針對這兩個配置的。
來看一下這幾個主要的步驟:
這部分的邏輯是在AbstractBeanDefinition類的prepareMethodOverrides方法中:
public void prepareMethodOverrides() throws BeanDefinitionValidationException { // Check that lookup methods exists. MethodOverrides methodOverrides = getMethodOverrides(); if (!methodOverrides.isEmpty()) { for (MethodOverride mo : methodOverrides.getOverrides()) { prepareMethodOverride(mo); } } } protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { // 獲取對應類中對應方法名的個數 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); if (count == 0) { throw new BeanDefinitionValidationException( "Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]"); } else if (count == 1) { // 標記MethodOverride暫未被覆蓋,避免參數類型檢查的開銷 mo.setOverloaded(false); } }
在Spring配置中存在lookup-method和replace-method兩個配置功能,而這兩個配置的加載其實就是將配置統一存放在BeanDefinition中的methodOverrides屬性裏,這兩個功能實現原理實際上是在bean實例化的時候若是檢測到存在methodOverrides屬性,會動態地爲當前bean生成代理並使用對應的攔截器爲bean作加強處理,這部分在建立bean部分會作詳細解析。
可是這裏要提到的是,對於方法的匹配來說,若是一個類中存在若干個重載方法,那麼,在函數調用及加強的時候還須要根據參數類型進行匹配,來最終確認當前調用的究竟是哪一個函數。可是,Spring將一部分匹配工做在這裏完成了,若是當前類中的方法只有一個,那麼就設置該方法沒有被重載,這樣在後續調用的時候即可以直接使用找到的方法,而不須要進行方法的參數匹配驗證了,並且還能夠提早對方法存在性進行驗證,正可謂一石二鳥,這部分須要結合後面的邏輯來理解,如今不理解能夠先忽略。
在真正調用doCreate方法建立bean實例前使用了方法resolveBeforeInstantiation()對BeanDefinition中的屬性作一些前置處理。這裏不管其中是否有相應的邏輯實現,咱們均可以理解,由於真正邏輯實現先後留有處理函數也是可擴展的一種體現。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
這裏最重要的無疑是兩個方法applyBeanPostProcessorsBeforeInstantiation以及applyBeanPostProcessorsAfterInitialization,其實現很是簡單,無非是對後處理器中全部InstantiationAwareBeanPostProcessor類型的後處理器進行postProcessBeforeInstantiation方法和BeanPostProcessor的postProcessAfterInitialization方法的調用。
實例化前的後處理器應用
bean的實例化前調用,也就是將AbstractBeanDefinition轉換爲BeanWrapper前的處理,這至關於給子類一個修改BeanDefinition的機會,也就是說當程序通過這個方法以後,bean可能已經不是咱們認爲的bean了,有多是一個通過處理的代理bean,多是經過cglib生成也多是經過其餘技術生成的,這個在後面涉及到AOP時會講到,如今咱們只須要知道,在bean的實例化前會調用後處理器的方法進行處理:
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } } return null; }
實例化後的後處理器應用
Spring中的規則是在bean初始化後儘量保證將註冊的後處理器的postProcessAfterInitialization方法應用到該bean中,由於若是返回的bean不爲空,那麼便不會再次經歷普通bean的建立過程,因此只能在這裏應用後處理器的postProcessAfterInitialization方法。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }
這裏還有一點很重要,在該函數中還有一個短路判斷,這個很關鍵:
if(bean != null) { return bean; }
當通過前置處理後返回的結果若是不爲空,那麼會直接略事後續的Bean建立而直接返回,這個地方很容易被忽視,可是卻起着相當重要的做用,咱們熟知的AOP功能就是基於這裏的判斷的,後面關於AOP的文章中也會涉及到。
當經歷過resolveBeforeInstantiation()方法後,若是建立了代理或者重寫了InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法並在方法postProcessBeforeInstantiation()中改變了bean,則直接返回就能夠了,不然就須要進行常規bean的建立,這是在doCreateBean中完成的:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 根據指定bean使用對應的策略建立新的實例,如:工廠方法、構造函數自動注入、簡單初始化 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { // 應用MergedBeanDefinitionPostProcessor applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // 是否須要提前曝光:單例&容許循環依賴&當前bean正在建立中,檢測循環依賴 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // 爲避免後期循環依賴,能夠在bean初始化完成前將建立實例的ObjectFactory加入工廠 addSingletonFactory(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { // 對bean再一次依賴引用,主要應用SmartInstantiationAwareBeanPostProcessor // 其中咱們熟知的AOP就是在這裏將advice動態織入bean中,若沒有則直接返回bean,不作任何處理 return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { // 對bean進行填充,將各個屬性值注入,其中,可能存在依賴於其餘bean的屬性,則會遞歸初始依賴bean populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { // 調用初始化方法,好比init-method exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); // earlySingletonReference只有在檢測到有循環依賴的狀況下才會不爲空 if (earlySingletonReference != null) { // 若是exposedObject沒有在初始化方法中被改變,也就是沒有被加強 if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) { // 檢測依賴 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } // 由於bean建立後其所依賴的bean必定是已經建立的, // actualDependentBeans不爲空則表示當前bean建立後其依賴的bean卻沒有所有 // 建立完,也就是說存在循環依賴 if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { // 根據scope註冊bean registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
咱們這裏只簡單看看整個函數的概要思路,各個部分詳細邏輯留待後文分析:
1. 若是是單例則須要首先清除緩存。
2. 建立bean實例,即將BeanDefinition轉換爲BeanWrapper。
轉換是一個複雜的過程,可是咱們仍是能夠嘗試歸納大體的功能,以下所示。
3. MergedBeanDefinitionPostProcessor的應用。
bean合併後的處理,Autowired註解正是經過此方法實現諸如類型的解析。
4. 依賴處理
在Spring會有循環依賴的狀況,例如,當A中含有B的屬性,而B中又含有A的屬性時就會構成一個循環依賴,此時若是A和B都是單例,那麼在Spring中的處理方式就是當建立B的時候,涉及自動注入A的步驟時,並非直接去再次建立A,而是經過放入緩存中的ObjectFactory來建立實例,這樣就解決了循環依賴問題。
5. 屬性填充。將全部的屬性填充至bean的實例中。
6. 循環依賴檢查。
Spring中只在單例下才會解決循環依賴,而對於prototype的bean,Spring沒有好的解決辦法,惟一要作的就是拋出異常。在這個步驟裏面會檢測已經加載的bean是否已經出現了依賴循環,並判斷是否須要拋出異常。
7. 註冊DisposableBean
若是配置了destroy-method,這裏須要註冊以便於在銷燬時候調用。
8. 完成建立並返回。
本文先從全局角度分析了bean建立的整個流程,而後着重分析了Spring在bean建立以前所作的一些準備工做,包括override屬性處理、實例化先後對後處理器的應用,這些都只是一些全局性的統籌工做,以後又看了一下bean建立的實際過程,後面就要開始詳細分析bean的建立過程了,這個纔是真正爬坡的開始。