Spring啓動過程——源碼分析(finishBeanFactoryInitialization(beanFactory))

前言

此篇是補充上篇未分析完的finishBeanFactoryInitialization部分
配合上篇食用效果更佳緩存

Spring啓動過程——源碼分析bash

finishBeanFactoryInitialization(beanFactory)

主要方法preInstantiateSingletons()
遍歷List beanNames
若是Bean 不是抽象&是單例&不是lazy

若是不是FactoryBean

getBean進入doGetBean 下面四張圖都是
doGetBean.1 app

doGetBean.2
doGetBean.3
doGetBean.4
若是是bean是單例
重點方法 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 post

真正建立Bean是createBean()

//通常用於建立aop代理 
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//若是上邊沒有代理 這裏會真正開始建立
Object beanInstance = doCreateBean(beanName, mbdToUse, args)
複製代碼

createBean->resolveBeforeInstantiation ui

doCreateBean.1
doCreateBean.2
doCreateBean.3
走向以下面流程圖 doCreateBean->createBeanInstance

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
bp instanceof MergedBeanDefinitionPostProcessor -> bp.postProcessMergedBeanDefinition(mbd, beanType, beanName)this

populateBean

爲剛剛實例化好的Bean進行屬性等賦值google

  • BeanWrapper爲null直接報錯或者returnspa

  • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
    官方的解釋是:讓用戶能夠自定義屬性注入。好比用戶實現一 個 InstantiationAwareBeanPostProcessor 類型的後置處理器,並經過 postProcessAfterInstantiation 方法向 bean 的成員變量注入自定義的信息。固然,若是無 特殊需求,直接使用配置中的信息注入便可。另外,Spring 並不建議你們直接實現 InstantiationAwareBeanPostProcessor 接口,若是想實現這種類型的後置處理器,更建議 經過繼承 InstantiationAwareBeanPostProcessorAdapter 抽象類實現自定義後置處理器prototype

  • 這裏會出現一個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)

  1. 判斷是不是InitializingBean的實現,執行接口規定的初始化afterPropertiesSet
  2. 執行invokeCustomInitMethod,方法大體是
    找出全部初始化方法(@Bean initMethod屬性指定的方法) mbd.getInitMethodName() 對應去執行

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
執行 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源碼看了我好幾天,收穫仍是挺大的,也總結

  1. 查看源碼前提:是必需要知道怎麼用
  2. 若是實在看不懂,能夠google找再總結
  3. 有時有些很底層的能夠先跳過,先直接到知道必將執行的方法打斷點,由後往前看方法棧debug(如FactoryBean這部分)

最後關於Spring總結 主要按着下面四點去看 1)、Spring容器在啓動,先保存Bean定義信息

  • xml註冊bean
  • 註解註冊Bean

2)、Spring容器會在XX的狀況下建立Bean

  • 用到這個bean的時候 去建立 *finishBeanFactoryInitialization 統一建立bean

3)、後置處理器 *每個Bean建立完成 會使用處理器處理

  • AutowiredAnnotationBeanPostProcessor 處理自動注入
  • XXXPostProcessor

4)、事件驅動模型 *ApplicationListener 事件監聽 *ApplicationEventMulticaster 事件派發

相關文章
相關標籤/搜索