国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring IOC 容器源碼分析 - 余下的初始化工作

Alfred / 3261人閱讀

摘要:簡介本篇文章是容器源碼分析系列文章的最后一篇文章,本篇文章所分析的對象是方法,該方法用于對已完成屬性填充的做最后的初始化工作。后置處理器是拓展點之一,通過實現后置處理器接口,我們就可以插手的初始化過程。

1. 簡介

本篇文章是“Spring IOC 容器源碼分析”系列文章的最后一篇文章,本篇文章所分析的對象是 initializeBean 方法,該方法用于對已完成屬性填充的 bean 做最后的初始化工作。相較于之前幾篇文章所分析的源碼,initializeBean 的源碼相對比較簡單,大家可以愉快的閱讀。好了,其他的不多說了,我們直入主題吧。

2. 源碼分析

本章我們來分析一下 initializeBean 方法的源碼。在完成分析后,還是像往常一樣,把方法的執行流程列出來。好了,看源碼吧:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        // 若 bean 實現了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等接口,則向 bean 中注入相關對象
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 執行 bean 初始化前置操作
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        /*
         * 調用初始化方法:
         * 1. 若 bean 實現了 InitializingBean 接口,則調用 afterPropertiesSet 方法
         * 2. 若用戶配置了 bean 的 init-method 屬性,則調用用戶在配置中指定的方法
         */
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 執行 bean 初始化后置操作,AOP 會在此處向目標對象中織入切面邏輯
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

以上就是 initializeBean 方法的邏輯,很簡單是不是。該方法做了如下幾件事情:

檢測 bean 是否實現了 *Aware 類型接口,若實現,則向 bean 中注入相應的對象

執行 bean 初始化前置操作

執行初始化操作

執行 bean 初始化后置操作

在上面的流程中,我們又發現了后置處理器的蹤影。如果大家閱讀過 Spring 的源碼,會發現后置處理器在 Spring 源碼中多次出現過。后置處理器是 Spring 拓展點之一,通過實現后置處理器 BeanPostProcessor 接口,我們就可以插手 bean 的初始化過程。比如大家所熟悉的 AOP 就是在后置處理 postProcessAfterInitialization 方法中向目標對象中織如切面邏輯的。關于“前置處理”和“后置處理”相關的源碼,這里就不分析了,大家有興趣自己去看一下。接下來分析一下 invokeAwareMethods 和 invokeInitMethods 方法,如下:

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            // 注入 beanName 字符串
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            // 注入 ClassLoader 對象
            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
        }
        if (bean instanceof BeanFactoryAware) {
            // 注入 BeanFactory 對象
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

invokeAwareMethods 方法的邏輯很簡單,一句話總結:根據 bean 所實現的 Aware 的類型,向 bean 中注入不同類型的對象。

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
        throws Throwable {

    // 檢測 bean 是否是 InitializingBean 類型的
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name "" + beanName + """);
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction() {
                    @Override
                    public Object run() throws Exception {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            // 如果 bean 實現了 InitializingBean,則調用 afterPropertiesSet 方法執行初始化邏輯
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 調用用戶自定義的初始化方法
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

invokeInitMethods 方法用于執行初始化方法,也不復雜,就不多說了。

3. 總結

本篇文章到這里差不多就分析完了,總的來說本文的內容比較簡單,很容易看懂。正如簡介一章中所說,本篇文章是我的“Spring IOC 容器源碼分析”系列文章的最后一篇文章。寫完這本篇文章,有種如釋重負的感覺。我在5月15號寫完 Java CAS 原理分析 文章后,次日開始閱讀 Spring IOC 部分的源碼,閱讀該部分源碼花了大概兩周的時間。然后在5月30號發布了“Spring IOC 容器源碼分析”系列文章的第一篇文章 Spring IOC 容器源碼分析系列文章導讀。在寫完第一篇文章后,就開啟了快速更新模式,以平均2天一篇的速度進行更新。終于在今天,也就是6月11號寫完了最后一篇。這一段時間寫文章寫的很累,經常熬夜。主要的原因在于,在自己看懂源碼的同時,通過寫文章的方式盡量保證別人也能看懂的話,這個就比較難了。比如我在閱讀源碼的時候,在源碼上面寫了一些簡單的注釋。這些注釋我可以看懂,但如果想寫成文章,則需要把注釋寫的盡量詳細,必要的背景知識也要介紹一下。總的來說,認真寫一篇技術文章還是不容易的。寫文章尚如此,那寫書呢,想必更加辛苦了。我在閱讀源碼和寫文章的過程中,也參考了一些資料(相關資料在“導讀”一文中指明了出處,本文就不再次說明)。在這里,向這些資料的作者表示感謝!

好了,本篇文章就到這里了,感謝大家的閱讀。

本文在知識共享許可協議 4.0 下發布,轉載需在明顯位置處注明出處
作者:coolblog.xyz
本文同步發布在我的個人博客:http://www.coolblog.xyz
附錄:Spring 源碼分析文章列表 Ⅰ. IOC
更新時間 標題
2018-05-30 Spring IOC 容器源碼分析系列文章導讀
2018-06-01 Spring IOC 容器源碼分析 - 獲取單例 bean
2018-06-04 Spring IOC 容器源碼分析 - 創建單例 bean 的過程
2018-06-06 Spring IOC 容器源碼分析 - 創建原始 bean 對象
2018-06-08 Spring IOC 容器源碼分析 - 循環依賴的解決辦法
2018-06-11 Spring IOC 容器源碼分析 - 填充屬性到 bean 原始對象
2018-06-11 Spring IOC 容器源碼分析 - 余下的初始化工作
Ⅱ. AOP
更新時間 標題
2018-06-17 Spring AOP 源碼分析系列文章導讀
2018-06-20 Spring AOP 源碼分析 - 篩選合適的通知器
2018-06-20 Spring AOP 源碼分析 - 創建代理對象
2018-06-22 Spring AOP 源碼分析 - 攔截器鏈的執行過程
Ⅲ. MVC
更新時間 標題
2018-06-29 Spring MVC 原理探秘 - 一個請求的旅行過程
2018-06-30 Spring MVC 原理探秘 - 容器的創建過程


本作品采用知識共享署名-非商業性使用-禁止演繹 4.0 國際許可協議進行許可。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69741.html

相關文章

  • Spring IOC 容器源碼分析系列文章導讀

    摘要:本文是容器源碼分析系列文章的第一篇文章,將會著重介紹的一些使用方法和特性,為后續的源碼分析文章做鋪墊。我們可以通過這兩個別名獲取到這個實例,比如下面的測試代碼測試結果如下本小節,我們來了解一下這個特性。 1. 簡介 Spring 是一個輕量級的企業級應用開發框架,于 2004 年由 Rod Johnson 發布了 1.0 版本。經過十幾年的迭代,現在的 Spring 框架已經非常成熟了...

    NSFish 評論0 收藏0
  • Spring IOC 容器源碼分析 - 創建單例 bean 過程

    摘要:關于創建實例的過程,我將會分幾篇文章進行分析。源碼分析創建實例的入口在正式分析方法前,我們先來看看方法是在哪里被調用的。時,表明方法不存在,此時拋出異常。該變量用于表示是否提前暴露單例,用于解決循環依賴。 1. 簡介 在上一篇文章中,我比較詳細的分析了獲取 bean 的方法,也就是getBean(String)的實現邏輯。對于已實例化好的單例 bean,getBean(String) ...

    mochixuan 評論0 收藏0
  • Spring AOP 源碼分析系列文章導讀

    摘要:在寫完容器源碼分析系列文章中的最后一篇后,沒敢懈怠,趁熱打鐵,花了天時間閱讀了方面的源碼。從今天開始,我將對部分的源碼分析系列文章進行更新。全稱是,即面向切面的編程,是一種開發理念。在中,切面只是一個概念,并沒有一個具體的接口或類與此對應。 1. 簡介 前一段時間,我學習了 Spring IOC 容器方面的源碼,并寫了數篇文章對此進行講解。在寫完 Spring IOC 容器源碼分析系列...

    張春雷 評論0 收藏0
  • Spring IOC 容器源碼分析 - 創建原始 bean 對象

    摘要:你也會了解到構造對象的兩種策略。構造方法參數數量低于配置的參數數量,則忽略當前構造方法,并重試。通過默認構造方法創建對象看完了上面冗長的邏輯,本節來看點輕松的吧通過默認構造方法創建對象。 1. 簡介 本篇文章是上一篇文章(創建單例 bean 的過程)的延續。在上一篇文章中,我們從戰略層面上領略了doCreateBean方法的全過程。本篇文章,我們就從戰術的層面上,詳細分析doCreat...

    sutaking 評論0 收藏0
  • Spring IOC 容器源碼分析 - 循環依賴解決辦法

    摘要:實例化時,發現又依賴于。一些緩存的介紹在進行源碼分析前,我們先來看一組緩存的定義。可是看完源碼后,我們似乎仍然不知道這些源碼是如何解決循環依賴問題的。 1. 簡介 本文,我們來看一下 Spring 是如何解決循環依賴問題的。在本篇文章中,我會首先向大家介紹一下什么是循環依賴。然后,進入源碼分析階段。為了更好的說明 Spring 解決循環依賴的辦法,我將會從獲取 bean 的方法getB...

    aikin 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<