分類
發燒車訊

spring 是如何注入對象的和bean 創建過程分析

文章目錄:

  1. 【本文】spring 是如何注入對象的

首先需要知道一個大致實現

  • 這個注入過程肯定是在 BeanPostProcessor 中實現的

  • spring 是在 beanFactory.getBean 進行 bean 實例化的,即懶加載

  • 根據第二條,也就是說在 getBean 的時候才會去調用所有 BeanPostProcessor

  • 第二篇文章說到,BeanFactory 的 refresh 過程只是註冊 BeanPostProcessor,真正執行在 getBean 方法中

  • MergedBeanDefinitionPostProcessor 也是一種 BeanPostProcessor 它重新弄了個一個生命周期函數,替代了 BeanPostProcessor 默認的生命周期函數,這麼看吧,我貼一小段源碼

    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }

    它允許你在非 BeanFactoryProcess 中去修改 Bean 定義

  • InstantiationAwareBeanPostProcessor 也是一種 BeanPostProcessor 它也重新定義了一個生命周期函數,它允許把屬性值注入到屬性對象中

@Autowired 加載定義的過程

我們先不看 bean 的創建過程,就看 MergedBeanDefinitionPostProcessor 的實現子類,這裏看名字猜測 AutowiredAnnotationBeanPostProcessor 應該就是干這件事的,所以我們接下來可以直接看 AutowiredAnnotationBeanPostProcessor 的 postProcessMergedBeanDefinition 方法的代碼。

順着方法的調用,可以知道在 buildAutowiringMetadata 是真正查找這些註解的地方,最後 checkConfigMembersMember 註冊進了 bean 定義,具體如何查找的讀者自行查看源碼。

這裏只是將 Member 註冊進了 bean 定義,真正實例化在填充 Bean 的過程中,下面說到 bean 的創建過程可以知道是何時注入的。

Bean 的創建過程

前面說到 spring 是在 getBean 的過程中進行 Bean 創建的,創建 bean 分為幾個步驟

  1. 獲取 bean 定義
  2. new Bean()
  3. 執行生命周期函數 (前)
  4. 創建依賴項
  5. 填充 bean
  6. 執行生命周期函數(后)

入口為 BeanFactory.getBean ,BeanFactory 的實現類為 DefaultListableBeanFactory 這些你可以在 BeanFactory 的 refresh 過程中找到

根據源碼,如果 bean 還不存在時,就會執行 bean 的創建流程

獲取 bean 定義在這段源碼中

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

緊跟着,根據 Bean 定義搜索其依賴項,並創建 bean ,可以看出是遞歸創建 bean

String[] dependsOn = mbd.getDependsOn();
for (String dep : dependsOn) {
    getBean(dep);
}

然後就創建 bean 了

if (mbd.isSingleton()) {
    createBean(beanName, mbd, args);
}

// 真正的執行在 doCreateBean 過程中
Object beanInstance = doCreateBean(beanName, mbdToUse, args);

創建 bean 第一步 new Bean

if (instanceWrapper == null) {
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}

創建 bean 第二步,執行所有的 processor ,包含 MergedBeanDefinitionPostProcessor ,所以在這一步註冊注入選項

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

創建 bean 第三步,填充 bean ,這裏做的 @Autowired 注入

populateBean(beanName, mbd, instanceWrapper);

最終的處理過程在 AutowiredAnnotationBeanPostProcessor 的 postProcessPropertyValues 函數中

metadata.inject(bean, beanName, pvs);

因為在前面已經獲取過依賴項,並且把其丟進了容器,所以這裡是直接用反射寫進去就可以了

創建 bean 第四步,初始化 bean ,這裡有一個方法注入,方法注入原來發生在初始化 bean 過程中,還有就是生命周期函數執行了,包含 BeanPostProcessor 的前置後置生命周期,初始化方法等

小說明 :AutowiredAnnotationBeanPostProcessor 即是 一個 MergedBeanDefinitionPostProcessor 也是一個 InstantiationAwareBeanPostProcessor

一點小推廣

創作不易,希望可以支持下我的開源軟件,及我的小工具,歡迎來 gitee 點星,fork ,提 bug 。

Excel 通用導入導出,支持 Excel 公式
博客地址:
gitee:

使用模板代碼 ,從數據庫生成代碼 ,及一些項目中經常可以用到的小工具
博客地址:
gitee:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!