23--Spring建立Bean的過程(五),填充bean的屬性過程簡析
阿新 • • 發佈:2018-12-10
上一小節我們簡介了一下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注入吧,那麼下面的章節,我們就來分析屬性注入的細節。