Spring原始碼系列:依賴注入(四)-總結

glmapper發表於2019-02-26

在上面三篇文章中對依賴注入做了一個大致的梳理;裡面都是大量程式碼的分析,本文在此基礎上進行一個總結歸納。

依賴注入呼叫過程

Spring原始碼系列:依賴注入(四)-總結

如前幾篇文章所述,依賴注入是由getBean來觸發的;然後涉及到bean例項的建立、依賴關係的建立、屬性注入等子過程。

  • getBean 方法觸發依賴注入
  • doGetBean 從容器中查詢Bean(BeanFactory鏈,當前容器->雙親容器-雙親容器…)

當然,在獲取到某個Bean的時候也會通過遞迴的方式來依賴注入依賴的bean

  • createBeanInstance 生成了Bean所包含的Java物件,Spring中用SimpleInstantiationStrategy類來生成Bean物件的例項,例項化Java物件的方法有兩種(CGlib是預設方式):

    • 通過BeanUtils,它使用了JVM的反射功能來生成Java物件例項
    • 用CGLIB來生成,CGLIB是一種常用的位元組碼生成器的類庫
  • populateBean 設定Bean物件的依賴關係

  • resolveValueIfNecessary 注入型別的處理;解析不同型別的屬性

  • setPropertyValues 屬性注入

關於lazy-init

Ioc容器的初始化過程中,主要的工作就是對BeanDefinition的定位、載入、解析和註冊;但是就像之前說過的,此時依賴注入還沒有發生。在Spring原始碼系列:依賴注入(一)getBean文中提到,依賴注入發生在應用第一次向容器獲取Bean的時候;也就是上面說到的通過getBean來觸發。

當然,依賴注入也可以在容器初始化的過程中就完成。這個就是lazy-init屬性的存在意義了。就是說我們可以通過設定Bean的lazy-init屬性來控制預例項化的過程。

預例項化:在初始化容器時完成Bean的依賴注入

這種做法的好處在於提高了我們第一次獲取Bean的的效率,但是它也降低了容器初始化的速度。(這個其實很好理解的,因為第一次獲取Bean的時候,依賴注入已經完成了,直接拿過來用就行)

關於lazy-init屬性的處理也是在wac.refresh這個方法中完成的,具體是在finishBeanFactoryInitialization方法中。如果繼續追溯的話,最終是交給DefaultListableBeanFactory容器中的preInstantiateSingletons方法中完成。

lazy-init這種例項化方式就是通過將依賴注入委託給容器來處理,而不是在使用者第一向容器申請的Bean的時候完成依賴注入,不同的階段,也有不同的優劣。

相關文章