前言
此篇是補充上篇未分析完的finishBeanFactoryInitialization部分
配合上篇食用效果更佳
finishBeanFactoryInitialization(beanFactory)
主要方法preInstantiateSingletons()遍歷List beanNames
如果Bean 不是抽象&是單例&不是lazy
如果不是FactoryBean
getBean進入doGetBean 下面四張圖都是
doGetBean.1
重點方法 getSingleton 大致執行如下
//先從快取中取 第一次進來時沒有值的
Object singletonObject = this.singletonObjects.get(beanName);
//存在 則return
if(singletonObject!=null) return;
//解決迴圈依賴
beforeSingletonCreation(beanName);
//真正建立bean
singletonObject = singletonFactory.getObject();
afterSingletonCreation(beanName);
//加入快取
addSingleton(beanName, singletonObject);
return singleObject
複製程式碼
真正建立Bean是createBean() 如果是bean是多例
//this.prototypesCurrentlyInCreation.set(beanName)
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
//this.prototypesCurrentlyInCreation.remove()
afterPrototypeCreation(beanName);
複製程式碼
單例多例建立Bean都會呼叫到createBean
真正建立Bean是createBean()//一般用於建立aop代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//如果上邊沒有代理 這裡會真正開始建立
Object beanInstance = doCreateBean(beanName, mbdToUse, args)
複製程式碼
createBean->resolveBeforeInstantiation
doCreateBean.1 doCreateBean.2 doCreateBean.3 走向如下面流程圖 doCreateBean->createBeanInstanceapplyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
bp instanceof MergedBeanDefinitionPostProcessor -> bp.postProcessMergedBeanDefinition(mbd, beanType, beanName)
populateBean
為剛剛例項化好的Bean進行屬性等賦值
-
BeanWrapper為null直接報錯或者return
-
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
官方的解釋是:讓使用者可以自定義屬性注入。比如使用者實現一 個 InstantiationAwareBeanPostProcessor 型別的後置處理器,並通過 postProcessAfterInstantiation 方法向 bean 的成員變數注入自定義的資訊。當然,如果無 特殊需求,直接使用配置中的資訊注入即可。另外,Spring 並不建議大家直接實現 InstantiationAwareBeanPostProcessor 介面,如果想實現這種型別的後置處理器,更建議 通過繼承 InstantiationAwareBeanPostProcessorAdapter 抽象類實現自定義後置處理器
- 這裡會出現一個Spring的內部processor:AutowiredAnnotationBeanPostProcessor 執行下去 進入postProcessProperties 首先找出所有的註解包括@Value @Autowired然後進行呼叫inject方法進行賦值 最終是通過反射實現最終賦值
Field field = (Field) this.member;
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
複製程式碼
applyPropertyValues(beanName, mbd, bw, pvs);
將屬性應用到 bean 物件中
-
檢測屬性值列表是否已轉換過的,若轉換過,則直接填充屬性,無需再次轉換
-
遍歷屬性值列表 pvs,解析原始值 originalValue,得到解析值 resolvedValue
-
對解析後的屬性值 resolvedValue 進行型別轉換
-
將型別轉換後的屬性值設定到 PropertyValue 物件中,並將 PropertyValue 物件存入 deepCopy 集合中
-
將 deepCopy 中的屬性資訊注入到 bean 物件中
流程圖:
exposedObject = initializeBean(beanName, exposedObject, mbd)
餘下的初始化工作
invokeAwareMethods(beanName, bean)若 bean 實現了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等介面,則向 bean 中注入相關物件 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
例項化前執行後置處理器對應的postProcessBeforeInitialization方法
invokeInitMethods(beanName, wrappedBean, mbd)
- 判斷是否是InitializingBean的實現,執行介面規定的初始化afterPropertiesSet
- 執行invokeCustomInitMethod,方法大致是
找出所有初始化方法(@Bean initMethod屬性指定的方法) mbd.getInitMethodName() 對應去執行
執行 bean 初始化後置操作,AOP 會在此處向目標物件中織入切面邏輯
如果是FactoryBean
FactoryBean一直都沒怎麼用過 所以自己寫了demo用下
@Autowired
private Student2 student2;
複製程式碼
debug一下 檢視下執行過程
發現它是在Student2.Class是在populateBean的時候呼叫processor進行inject時被例項化的,此時發現是FactoryBean就直接被呼叫了getObject 拿到這個bean 也就是說,一開始被例項化的只有MyFactoryBean這個類,而沒有Student2這個類MyFactoryBean此時beanName=&myFactoryBean
總結
這次Spring ioc原始碼看了我好幾天,收穫還是挺大的,也總結
- 檢視原始碼前提:是必須要知道怎麼用
- 如果實在看不懂,可以google找再總結
- 有時有些很底層的可以先跳過,先直接到知道必將執行的方法打斷點,由後往前看方法棧debug(如FactoryBean這部分)
最後關於Spring總結 主要按著下面四點去看 1)、Spring容器在啟動,先儲存Bean定義資訊
- xml註冊bean
- 註解註冊Bean
2)、Spring容器會在XX的情況下建立Bean
- 用到這個bean的時候 去建立 *finishBeanFactoryInitialization 統一建立bean
3)、後置處理器 *每一個Bean建立完成 會使用處理器處理
- AutowiredAnnotationBeanPostProcessor 處理自動注入
- XXXPostProcessor
4)、事件驅動模型 *ApplicationListener 事件監聽 *ApplicationEventMulticaster 事件派發