在上篇文章刨坑的過程當中,順便研究了一波spring源碼,初始看的也是頭暈,後面逐漸捋好了思路。我的感受spring仍是個大工程的,這篇文章解讀的確定也有本身理解不到位的部分,但願各位看官能多討論討論。最後會附上一副getBean方法的流程圖,但願能打開你們看這部分源碼的思路。(本文基於spring 5.1.2版本)spring
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { //會包括解析別名等操做 final String beanName = transformedBeanName(name); Object bean; // 先檢查單例列表中是否已經註冊了這個bean Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 檢查bean是否併發被建立 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 檢查是否在父類工廠中,邏輯和這個差很少,這裏省略.... //標記bean正在被建立 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { //合併父類中的方法及屬性,下面會細講 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); //檢查這個bean是否爲抽象類 checkMergedBeanDefinition(mbd, beanName, args); // 這裏是爲了保證獲取的bean的依賴都須要先生成 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 ex; } } } // 建立單例的bean,看下方的createBean方法 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } 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); } 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, () -> { 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) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 檢查須要的類型和實際傳參類型是否一致. 這裏省略.... return (T) bean; }
整個操做大概是如下幾步:數組
這裏這麼設計是爲了解決循環依賴的問題。若A依賴B,B依賴C,C又依賴A,這樣三個bean就造成了一個環(這裏只是針對set方法注入的bean,構造器注入仍是會有循環依賴的問題而拋出異常的),spring會將建立的bean實例提早暴露在緩存中,一旦下一個bean建立的時候須要依賴上個bean,則直接使用ObjectFactory來獲取bean。緩存
這裏舉個生活中的例子闡述下:就拿建一個小區房來講,建房子是一個很複雜的工序,可是我們只要把架子搭好,告訴你們這塊地是用來建這個房子的就行。至於其餘裝修,傢俬等等東西均可之後面再進行補充。我們不能搭架子的時候去放傢俱吧,這樣整個都會亂套,也不符合常理。(這裏房子的框架是我們程序中的一個對象A,傢俱是另外一個對象B,A依賴B,B依賴A)數據結構
相關的邏輯有用到如下代碼段:
併發
每次singleton bean創造以前都會調用的方法,在singletonsCurrentlyInCreation容器中加入這個bean的beanName,標記這個bean正在建立中,供後期生成ObjectFactory。這裏有個inCreationCheckExclusions容器,在這裏我理解爲屬於該容器的bean必需要初始化完成才容許被獲取。也就是說,添加進該容器後bean便不會容許早期的循環依賴了。app
上面的代碼片斷的調用在doCreateBean源碼中(排在bean對象建立以後和屬性注入以前),能夠觀察到要執行addSingletonFactory方法須要知足三個條件:框架
在知足這三個條件的狀況下,會在singletonFactories容器中緩存一個生成該bean的工廠,將其提早暴露出去。這裏關注下getEarlyBeanReference(beanName, mbd, bean)這個方法,實際上ObjectFactory中getObject方法調用的也是這個方法。編輯器
看這部分以前,首先得明白BeanDefinition是用來幹什麼的,這個類會在整個源碼解析過程當中出現無數次。Spring把BeanDefinition定義成IOC容器的內部數據結構,實際上它也就是POJO對象在IOC容器中的抽象,經過這個對象,IOC容器能很方便的對Bean進行管理,包括利用它進行屬性的注入等等...ide
protected RootBeanDefinition getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) throws BeanDefinitionStoreException { synchronized (this.mergedBeanDefinitions) { RootBeanDefinition mbd = null; // 從新去獲取一次,有可能該BeanDefinition已經生成 if (containingBd == null) { mbd = this.mergedBeanDefinitions.get(beanName); } if (mbd == null) { if (bd.getParentName() == null) { // 沒有父類則深拷貝一個RootBeanDefinition if (bd instanceof RootBeanDefinition) { mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); } else { mbd = new RootBeanDefinition(bd); } } else { // 有父類則須要先獲取父類的BeanDefinition,流程和獲取子類的BeanDefinition一致 BeanDefinition pbd; try { String parentBeanName = transformedBeanName(bd.getParentName()); if (!beanName.equals(parentBeanName)) { pbd = getMergedBeanDefinition(parentBeanName); } else { BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without an AbstractBeanFactory parent"); } } } catch (NoSuchBeanDefinitionException ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); } //這裏進行深拷貝,並將子類重寫的方法和屬性進行覆蓋 mbd = new RootBeanDefinition(pbd); mbd.overrideFrom(bd); } // 若前面沒配置scope類型,這裏設置爲單例範圍 if (!StringUtils.hasLength(mbd.getScope())) { mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON); } // 這裏對內部類作了一些處理,若包含它的bean不是單例的,則該bean也將不會是單例的 if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) { mbd.setScope(containingBd.getScope()); } // 將生產的BeanDefinition 緩存起來 if (containingBd == null && isCacheBeanMetadata()) { this.mergedBeanDefinitions.put(beanName, mbd); } } return mbd; } }
這一部分應該仍是很容易理解的,這裏面出現了兩個Map,一個是dependentBeanMap,它主要用來裝載鍵爲beanName值爲dependentBeanName的容器,另外一個dependenciesForBeanMap是用來裝載鍵爲dependentBeanName值爲beanName的容器,這樣能夠方便咱們觀察一個類須要組裝哪些依賴,而後這個類同時是哪些類的依賴。源碼分析
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { //先去singletonObjects容器中去獲取,能獲取到就直接返回了 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { //調用destroySingletons方法singletonsCurrentlyInDestruction屬性纔會變成true if (this.singletonsCurrentlyInDestruction) { throw new Exception("xx")); } //這裏會將beanName緩存到singletonsCurrentlyInCreation集合中 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { //這裏會觸發下面的createBean方法 singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // 若是是與此同時被建立了,則直接獲取,若是能獲取到值不爲null,則正常返回。 //(注意這裏捕獲異常正常返回的話就不會走下面的addSingleton方法了。) singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } //這裏會將beanName從singletonsCurrentlyInCreation集合中移除 afterSingletonCreation(beanName); } if (newSingleton) { //添加到singletonObjects和registeredSingletons緩存中,並從singletonFactories和earlySingletonObjects中移除 addSingleton(beanName, singletonObject); } } return singletonObject; } }
這一塊不是很複雜,複雜的地方在doCreateBean這個方法中。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; // 要保證RootBeanDefinition的beanClass是存在的 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // 這一塊沒什麼研究,註解意思是(檢查全部帶有override的方法是否都是存在的) try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { } try { //這一塊我猜想大概是看我們本身有提供實例化的方法不,如有,則不會走下面的doCreateBean方法。 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { } try { //建立bean的真正方法 Object beanInstance = doCreateBean(beanName, mbdToUse, args); } return beanInstance; } catch (Exception e){ throw e; } }
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 建立這個bean,真正構建時有分兩種狀況,jdk反射和cglib動態代理 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 容許後置處理器來修改這個BeanDefinition synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // 用來解決循環依賴問題的,上面已經有過詳細解釋了。看上面循環依賴模塊 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { //進行屬性的注入,調用bean的set方法進行字段的初始化 populateBean(beanName, mbd, instanceWrapper); //進行一些初始化方法的調用,好比afterPropertiesSet等等。 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } //在出現循環依賴後,從earlySingletonObjects中獲取的bean對象和initializeBean後 //的不一致,證實被後置處理器處理過了,先後bean不一致,須要拋出異常 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } 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."); } } } } // 註冊bean的銷燬方法 try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
doCreateBean大概有如下步驟:
這裏是createBeanInstance方法中最終調用的方法,這裏有三個流程:
下面關注幾個重點代碼,省略了一些代碼,能夠本身去翻閱下:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { ...... PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 這裏是根據bean名稱進行依賴注入的 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 這裏是根據bean的類型進行依賴注入的 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } ...... if (pvs != null) { //實際上注入屬性值的方法,這裏是populateBean方法的重點 applyPropertyValues(beanName, mbd, bw, pvs); } }
這裏註釋下applyPropertyValues的部分源碼:
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { MutablePropertyValues mpvs = null; List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // 這裏能夠迅速返回。當這個PropertyValues對象中的值都是處理事後即可以觸發。狀態值會在下面幾行代碼設置。 try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // 這裏是個深拷貝,解析全部引用的值。 List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); //這裏的resolveValueIfNecessary是一個須要關注的方法,有興趣的小夥伴能夠點進去看看, //裏面封裝了針對各類類型的屬性的解析,例如List,Map,Set等等類型。 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } //爲了不每次建立都去轉換屬性 if (resolvedValue == originalValue) { //這裏的觸發條件必須爲該屬性得是有寫權限的,而且裏面不能帶有「.」和「[」這個符號,這裏個人理解是 //teacher.name以及student[1].name這樣的propertyName便不能觸發這個條件 if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { //這一塊的條件比上一個多了幾個,源值必須是string類型,且不能是動態的,而且不能是集合和數組中的任意一個。 pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { //條件在這裏觸發後就不會打開快捷返回的開關了 resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } //設置converted狀態值,供其組裝屬性時快捷返回。 if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // 將咱們深拷貝出來的值設置到包裝類BeanWrapperImpl包裝的對象上 try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
setPropertyValues方法的源碼最終調用的是AbstractNestablePropertyAccessor類的setPropertyValue方法,在這裏BeanWrapperImpl是它的實現類,從名字上看也能猜出來這個類是個處理嵌套屬性的訪問器。
public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException { AbstractNestablePropertyAccessor nestedPa; try { //這裏能夠解析嵌套的屬性 nestedPa = getPropertyAccessorForPropertyPath(propertyName); } catch (NotReadablePropertyException ex) { throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex); } //這裏獲取到了最終解析到的屬性名 PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName)); //給最終解析到的屬性名賦值操做 nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value)); }
上面有個getPropertyAccessorForPropertyPath方法,點進去會發現他會有個解析「.」和「[]」的方法getNestedPropertySeparatorIndex,它的做用我舉個例子來講明一下:一個班級有多個學生,我想設置某個學生的名字,班級是個Class對象,裏面有屬性:private Student[] students
這裏我想修改下student[2]的name屬性,我就必須先用getStudent方法取出 Student[] 數組,而後再在 Student[] 數組中找到索引爲2的Student,最後修改Student身上的name屬性。(這一塊不是很理解的能夠參考下BeanWrapper 源碼分析)