1. 程式人生 > >beanfactory中單例bean的初始化過程(一)

beanfactory中單例bean的初始化過程(一)

Date 10.06 pm

Point

完成beanfactory中單例bean的初始化

beanFactory.preInstantiateSingletons()

  1. 拿到所有的bean定義資訊(在 beanDefinitionNames中,遍歷list
  2. 獲取到bean的定義資訊
  3. 如果這個bean不是抽象,是單例,不是懶載入的
  4. 判斷這個bean是否factorybean(判斷這個bean有沒有實現factoryBean介面),是的話,用工廠裡面的方法去建立bean。

    • 呼叫getbean(&beanname) 獲取到beanFactory物件。
  5. 呼叫getBean(beanName)
    建立bean
    • 呼叫 doGetBean()
    • transformedBeanName進入這個方法將之前工廠bean的字首去除,將別名轉成正式的名稱
    • getSingleton檢測單例快取中是否有已構建的單例項bean,有就直接返回這個單例bean

      /** Cache of singleton objects: bean name to bean instance. */
      private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
      所有例項過的單例bean都會在這注冊,檢查的時候還會判斷當前bean有沒有在建立過程中。如果有的話,會在earlySingletonObjects
      去獲取,要是這個還是沒有獲取到的話,會去singletonFactories這個map中去獲取,要是獲取到的話就刪除singletonFactories中的bean,轉而在earlySingletonObjects這個map裡面去註冊
    • 沒有獲取到bean(開始建立bean的流程)
      • 就先判斷下我們是不是正在建立這個bean的例項,避免迴圈引用的問題。
      • 獲取bean的父工廠(這個主要是如果有Springmvc的話 可能會有這種父子工廠)這個父工廠要是能獲取到的話,又會去呼叫父工廠的dogetbean方法,獲取不到父工廠的話直接下一步
      • 標記當前bean已經建立,大概就是把當前beanname放到Collections.newSetFromMap(new ConcurrentHashMap<>(256))
        裡面,防止多執行緒的時候多次建立單例bean
      • 獲取bean的定義資訊
      • 獲取bean所依賴的其他bean,如果有,還是呼叫getbean的方式去構建那些依賴的bean
      • 如果這個bean是單例bean,回掉createBean,開始單例bean建立
        • 拿到bean的定義資訊
        • 解析bean的定義的型別,檢查這個定義資訊中的beanClass是不是為空
        • 檢測是否有bean方法被重寫,有的話準備重寫這個bean方法(也是檢查bean定義資訊裡面的methodOverrides這個屬性有沒有值)
        • 讓BeanPostProcessor提前攔截,返回代理物件resolveBeforeInstantiation()
          • 先根據定義資訊中的beforeInstantiationResolved判斷初始化之前有沒有處理,有的話就不進入這個processor中了,
          • 然後判斷這個值是不是由application定義的 和 判斷當前factory中已經有了InstantiationAwareBeanPostProcessor這個processor了,然後去獲取這個bean的目標class,然後呼叫InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation啟動前置處理器,然後如果返回的bean有值的話,再呼叫applyBeanPostProcessorsAfterInitialization後置處理器,然後將bean定義資訊中beforeInstantiationResolved這個引數賦值成這個返回的bean,然後返回這個bean

https://github.com/fulln