1. 程式人生 > >23--Spring建立Bean的過程(五),填充bean的屬性過程簡析

23--Spring建立Bean的過程(五),填充bean的屬性過程簡析

上一小節我們簡介了一下Spring中的迴圈依賴,並簡單介紹了Spring對Setter迴圈依賴的解決方法,好讓大家對接下來的分析有所準備,在

中我們已經分析了Spring通過無參和實參兩種方式建立bean的例項,接下來我們會分析建立bean例項之後的操作:填充bean的屬性,該過程大概可分為以下步驟

  • ① 前置判斷,對BeanWrapper的合法性進行判斷
  • ② 應用InstantiationAwareBeanPostProcessor處理器,在設定屬性之前,給InstantiationAwareBeanPostProcessor一個修改bean狀態的機會
  • ③ 如果InstantiationAwareBeanPostProcessor停止了對bean屬性的填充,則直接返回
  • ④ 解析自動裝配型別,對byName注入和byType注入做處理
  • ⑤ 判斷是否有InstantiationAwareBeanPostProcessors處理器,並進行處理
  • ⑥ 依賴檢查
  • ⑦ 應用屬性

以上就是填充bean的屬性的準備工作,而且屬性填充工作的原始碼比較多,本來只是想一個用一個小節來寫,但是原始碼實在太多,而且處理的各種分支情況也比較多,例如byName,byTpye,迴圈依賴處理,屬性轉換等。本小節就先來分析一下填充bean屬性的過程,讓大家先有所瞭解,其中的細節我們在接下來的章節中分析。

先來看下填充bean的屬性的準備工作的原始碼。

protected void populateBean
(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // ① 前置判斷 // 如果BeanWrapper物件為null,則說明沒有bean的例項 if (bw == null) { // RootBeanDefinition中有屬性,但是bean的例項為空,丟擲異常 if (mbd.hasPropertyValues()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"
); } else { // RootBeanDefinition中沒有屬性,直接返回 return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. // ② 應用InstantiationAwareBeanPostProcessor處理器 // 在設定屬性之前,給InstantiationAwareBeanPostProcessor一個修改bean狀態的機會 boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 是否繼續填充bean屬性 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } // ③ 如果InstantiationAwareBeanPostProcessor停止了對bean屬性的填充,則直接返回 if (!continueWithPropertyPopulation) { return; } // 獲取PropertyValues屬性 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // ④ 解析自動裝配型別 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // byName注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // byType注入 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // ⑤ 判斷是否有InstantiationAwareBeanPostProcessors處理器,並進行處理 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } // ⑥ 依賴檢查 if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } // ⑦ 應用屬性 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }

就對於步驟分析來講,還是比較簡單的,通過大家這幾天大家對Spring原始碼的分析,相信大家也可以得出Spring對函式處理的一貫套路

  • 前置判斷合法條件
  • 應用各種處理器
  • 將複雜的邏輯拆分成簡單的的分支
  • 對快取處理
  • 異常的處理
  • 。。。

而且大家可以發現,Spring很少在一個方法裡寫大量的程式碼,處理複雜的邏輯,是通過不斷的拆分業務邏輯,逐漸分解成簡單易懂的方法,這也是在開發中值得大家借鑑的地方。

Spring對bean屬性的填充這段程式碼很枯燥,如果有什麼吸引大家的地方,可能就是byName和byType注入吧,那麼下面的章節,我們就來分析屬性注入的細節。