1. 程式人生 > >Spring依賴註入源碼閱讀筆記

Spring依賴註入源碼閱讀筆記

方法 ani abs 判斷 val OS depends 好的 深拷貝

一、調用棧

一次典型的Spring依賴註入的調用棧:

  1. DefaultListableBeanFactory:getBean()
  2. AbstractBeanFactory:doGetBean()
  3. AbstractAutowireCapableBeanFactory:createBean()
  4. AbstractAutowireCapableBeanFactory:createBeanInstance()
  5. SimpleInstantiationStategy:instantiate()
  6. AbstractAutowireCapableBeanFactory:populateBean()
  7. AbstractAutowireCapableBeanFactory:applyPropertyValues()
  8. BeanDefinitionValueResolver:resolveValueIfNecessary()
  9. BeanDefinitionValueResolver:resolveReference()

二、依賴註入過程

  1. getBean:依賴註入的入口,處理參數調用doGetBean()
  2. doGetBean:檢查是否需要創建bean,並取得beanDefinition;
    • 單例Bean的處理,從Singleton的緩存中能取到,那就不需要創建。查找緩存的過程:先從singletonObjects中查找;如果沒有查找到,又是正在創建的bean,則從earlySingletonObjects中查找;仍未查找到,則通過singletonFactories
      取得。
    • 原型模式Bean的循環依賴檢測,如果檢測到正在創建(在prototypesCurrentlyInCreation[threadLocal]中存在),則拋出異常,因為此時,很有可能已經發生了循環依賴。
    • 向上遞歸查找beanDefinition,當前BeanFactory中不存在該bean的定義,則向父beanFactory遞歸調用getBean,直到找到為止。
    • 合並父BeanDefinition以取得RootBeanDefinition,如果獲取到的bean definition是一個子bean definition,則getMergedLocalBeanDefinition將它與父bean definition合並成一個root bean definition
    • RootBeanDefinition的合法性檢測:是否abstract
    • bean定義中顯式聲明的dependsOn,先進行初始化(遞歸的):並註冊依賴關系,如果檢測到循環依賴,則拋出異常。
    • 創建Bean的輔助處理
      • 單例bean:
        1. singletonObjects上鎖
        2. 把beanName加入到singletonsCurrentlyInCreation
        3. 創建Bean
        4. singletonsCurrentlyInCreation中移除beanName
        5. 解除singletonObjects鎖定
        6. 如果過程中創建了一個實例,將它放入singletonObjectsregisteredSingletons,並從singletonFactoriesearlySingletonObjects中移除
        7. 如果過程中發生了異常,將它從singletonObjectsregisteredSingletonssingletonFactoriesearlySingletonObjects中移除
        8. 處理FactoryBean
      • 原型模式bean:
        1. prototypesCurrentlyInCreation中加入beanName
        2. 創建Bean
        3. prototypesCurrentlyInCreation中移除beanName
        4. 處理FactoryBean
      • 其余scope的bean處理:
        1. 檢測scope是否存在
        2. 調用scope.get()方法,並傳入getObject()回調。回調中的處理,與prototype下基本一致。
        3. 處理FactoryBean
    • 處理返回數據類型,檢測是否可轉為requiredType
  3. createBean:創建出一個bean實例,初始化該實例,調用postprocessors等
    • 解析出Class類型,即解析出一個Class<?>,賦到rootBeanDefinition中。但不能直接復制,需要拷貝出一個新的rootBeanDefinition,因為mergedBeanDefinition是共享的,可能有動態解析的class類型,直接賦值可能會有問題。
    • 預處理重寫方法,檢測重寫的方法是否存在,並判斷是否是overload。
    • 調用一遍postprocessors調用InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation,這裏有可能會返回一個bean的代理。如果返回了bean的代理,那麽它將直接執行beanProcessor的postProcessAfterInitialization方法,並返回。
    • 調用鉤子方法doCreateBean
  4. doCreateBean
    • 從緩存中移除同名beanfactoryBeanInstanceCache中移除同名bean
    • 創建Bean實例 createBeanInstance
    • 調用一遍postprocessors調用MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition
    • Singleton循環依賴的處理:提前將剛創建的實例(未初始化的),放入緩存 如果是Singleton Bean並允許循環依賴,則將剛創建好的實例,放入singletonFactoriesregisteredSingletons中,並從earlySingletonObjects中將同名bean移除
    • Bean初始化 populateBean,用bean definition中的property values初始化得到的bean實例
    • 執行Spring擴展的初始化 initializeBean
      • invokeAwareMethods 如果bean實現了Aware的一些子接口,如BeanNameAware,則將相應的屬性set到bean中
      • 調用一遍postprocessors 調用BeanPostProcessor的postProcessBeforeInitialization方法
      • invokeInitMethods
        • 如果bean實現了InitializingBean接口,執行afterPropertiesSet()回調
        • 如果在bean definition中顯式自定義了init-method,則會執行一次initMethod回調(通過反射調用)
      • 調用一遍postprocessors 調用BeanPostProcessor的postProcessAfterInitialization方法
    • 註冊bean銷毀方法回調
  5. createBeanInstance:使用不同的策略,創建bean實例
    • 工廠方法 : 如果在bean definition中顯式聲明了factory-mothod,則調用工廠方法創建實例。
    • 構造函數 : 選擇合適的構造函數實例化
    • CGLIB : 利用CGLIB實例化
  6. populateBean
    • 取得bean definition的property values
    • 調用一遍postprocessors調用InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation方法
    • 處理autowire的註入 autowireByNameautowireByType
    • 調用一遍postprocessors調用InstantiationAwareBeanPostProcessorpostProcessPropertyValues方法
    • 對屬性進行註入 applyPropertyValues,屬性值註入,解析出運行時該bean factory中其他bean的引用。
      • 獲取BeanDefinitionValueResolver。
      • 創建一個新的PropertyValue的list,作為存放解析後的PropertyValue的容器。必須是深拷貝的,否則會修改到原bean definition中的property values。
      • 解析property value:resolveValueIfNecessary()
        針對不同類型的value對象,有不同的convert方式,如value是RuntimeBeanReference類型的,遞歸調用getBean方法,獲取bean。
      • 用BeanWrapper的setPropertyValues方法,批量為bean的屬性賦值。最終是調用bean的setXXX()方法賦值。

三、postprocessors及關鍵方法執行順序

  1. InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()
  2. createBeanInstance
  3. MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition()
  4. InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation()
  5. autowireByName;autowireByType
  6. InstantiationAwareBeanPostProcessorpostProcessPropertyValues()
  7. applyPropertyValues
  8. BeanPostProcessorpostProcessPropertyValues()
  9. InstantiationAwareBeanPostProcessorpostProcessBeforeInitialization()
  10. invokeInitMethods
  11. InstantiationAwareBeanPostProcessorpostProcessAfterInitialization()

Spring依賴註入源碼閱讀筆記