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

資訊專欄INFORMATION COLUMN

Spring IOC 容器源碼分析 - 創(chuàng)建單例 bean 的過(guò)程

mochixuan / 3171人閱讀

摘要:關(guān)于創(chuàng)建實(shí)例的過(guò)程,我將會(huì)分幾篇文章進(jìn)行分析。源碼分析創(chuàng)建實(shí)例的入口在正式分析方法前,我們先來(lái)看看方法是在哪里被調(diào)用的。時(shí),表明方法不存在,此時(shí)拋出異常。該變量用于表示是否提前暴露單例,用于解決循環(huán)依賴。

1. 簡(jiǎn)介

在上一篇文章中,我比較詳細(xì)的分析了獲取 bean 的方法,也就是getBean(String)的實(shí)現(xiàn)邏輯。對(duì)于已實(shí)例化好的單例 bean,getBean(String) 方法并不會(huì)再一次去創(chuàng)建,而是從緩存中獲取。如果某個(gè) bean 還未實(shí)例化,這個(gè)時(shí)候就無(wú)法命中緩存。此時(shí),就要根據(jù) bean 的配置信息去創(chuàng)建這個(gè) bean 了。相較于getBean(String)方法的實(shí)現(xiàn)邏輯,創(chuàng)建 bean 的方法createBean(String, RootBeanDefinition, Object[])及其所調(diào)用的方法邏輯上更為復(fù)雜一些。關(guān)于創(chuàng)建 bean 實(shí)例的過(guò)程,我將會(huì)分幾篇文章進(jìn)行分析。本篇文章會(huì)先從大體上分析 createBean(String, RootBeanDefinition, Object[])方法的代碼邏輯,至于其所調(diào)用的方法將會(huì)在隨后的文章中進(jìn)行分析。

好了,其他的不多說(shuō),直接進(jìn)入正題吧。

2. 源碼分析 2.1 創(chuàng)建 bean 實(shí)例的入口

在正式分析createBean(String, RootBeanDefinition, Object[])方法前,我們先來(lái)看看 createBean 方法是在哪里被調(diào)用的。如下:

public T doGetBean(...) {
    // 省略不相關(guān)代碼
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, new ObjectFactory() {
            @Override
            public Object getObject() throws BeansException {
                try {
                    return createBean(beanName, mbd, args);
                }
                catch (BeansException ex) {
                    destroySingleton(beanName);
                    throw ex;
                }
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    // 省略不相關(guān)代碼
}

上面是 doGetBean 方法的代碼片段,從中可以發(fā)現(xiàn) createBean 方法。createBean 方法被匿名工廠類的 getObject 方法包裹,但這個(gè)匿名工廠類對(duì)象并未直接調(diào)用 getObject 方法。而是將自身作為參數(shù)傳給了getSingleton(String, ObjectFactory)方法,那么我們接下來(lái)再去看看一下getSingleton(String, ObjectFactory) 方法的實(shí)現(xiàn)。如下:

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
    Assert.notNull(beanName, ""beanName" must not be null");
    synchronized (this.singletonObjects) {
        // 從緩存中獲取單例 bean,若不為空,則直接返回,不用再初始化
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName,
                        "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                        "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Creating shared instance of singleton bean "" + beanName + """);
            }
            /* 
             * 將 beanName 添加到 singletonsCurrentlyInCreation 集合中,
             * 用于表明 beanName 對(duì)應(yīng)的 bean 正在創(chuàng)建中
             */
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet();
            }
            try {
                // 通過(guò) getObject 方法調(diào)用 createBean 方法創(chuàng)建 bean 實(shí)例
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                // 將 beanName 從 singletonsCurrentlyInCreation 移除
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                /* 
                 * 將  鍵值對(duì)添加到 singletonObjects 集合中,
                 * 并從其他集合(比如 earlySingletonObjects)中移除 singletonObject 記錄
                 */
                addSingleton(beanName, singletonObject);
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

上面的方法邏輯不是很復(fù)雜,這里簡(jiǎn)單總結(jié)一下。如下:

先從 singletonObjects 集合獲取 bean 實(shí)例,若不為空,則直接返回

若為空,進(jìn)入創(chuàng)建 bean 實(shí)例階段。先將 beanName 添加到 singletonsCurrentlyInCreation

通過(guò) getObject 方法調(diào)用 createBean 方法創(chuàng)建 bean 實(shí)例

將 beanName 從 singletonsCurrentlyInCreation 集合中移除

映射緩存到 singletonObjects 集合中

從上面的分析中,我們知道了 createBean 方法在何處被調(diào)用的。那么接下來(lái)我們一起深入 createBean 方法的源碼中,來(lái)看看這個(gè)方法具體都做了什么事情。

2.2 createBean 方法全貌

createBean 和 getBean 方法類似,基本上都是空殼方法,只不過(guò) createBean 的邏輯稍微多點(diǎn),多做了一些事情。下面我們一起看看這個(gè)方法的實(shí)現(xiàn)邏輯,如下:

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating instance of bean "" + beanName + """);
    }
    RootBeanDefinition mbdToUse = mbd;

    // 解析 bean 的類型
    Class resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    try {
        // 處理 lookup-method 和 replace-method 配置,Spring 將這兩個(gè)配置統(tǒng)稱為 override method
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        // 在 bean 初始化前應(yīng)用后置處理,如果后置處理返回的 bean 不為空,則直接返回
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    // 調(diào)用 doCreateBean 創(chuàng)建 bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean "" + beanName + """);
    }
    return beanInstance;
}

上面的代碼不長(zhǎng),代碼的執(zhí)行流程比較容易看出,這里羅列一下:

解析 bean 類型

處理 lookup-method 和 replace-method 配置

在 bean 初始化前應(yīng)用后置處理,若后置處理返回的 bean 不為空,則直接返回

若上一步后置處理返回的 bean 為空,則調(diào)用 doCreateBean 創(chuàng)建 bean 實(shí)例

下面我會(huì)分節(jié)對(duì)第2、3和4步的流程進(jìn)行分析,步驟1的詳細(xì)實(shí)現(xiàn)大家有興趣的話,就自己去看看吧。

2.2.1 驗(yàn)證和準(zhǔn)備 override 方法

當(dāng)用戶配置了 lookup-method 和 replace-method 時(shí),Spring 需要對(duì)目標(biāo) bean 進(jìn)行增強(qiáng)。在增強(qiáng)之前,需要做一些準(zhǔn)備工作,也就是 prepareMethodOverrides 中的邏輯。下面來(lái)看看這個(gè)方法的源碼:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    MethodOverrides methodOverrides = getMethodOverrides();
    if (!methodOverrides.isEmpty()) {
        Set overrides = methodOverrides.getOverrides();
        synchronized (overrides) {
            // 循環(huán)處理每個(gè) MethodOverride 對(duì)象
            for (MethodOverride mo : overrides) {
                prepareMethodOverride(mo);
            }
        }
    }
}

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    // 獲取方法名為 mo.getMethodName() 的方法數(shù)量,當(dāng)方法重載時(shí),count 的值就會(huì)大于1
    int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
    // count = 0,表明根據(jù)方法名未找到相應(yīng)的方法,此時(shí)拋出異常
    if (count == 0) {
        throw new BeanDefinitionValidationException(
                "Invalid method override: no method with name "" + mo.getMethodName() +
                "" on class [" + getBeanClassName() + "]");
    }
    // 若 count = 1,表明僅存在已方法名為 mo.getMethodName(),這意味著方法不存在重載
    else if (count == 1) {
        // 方法不存在重載,則將 overloaded 成員變量設(shè)為 false
        mo.setOverloaded(false);
    }
}

上面的源碼中,prepareMethodOverrides方法循環(huán)調(diào)用了prepareMethodOverride方法,并沒(méi)其他的太多邏輯。主要準(zhǔn)備工作都是在 prepareMethodOverride 方法中進(jìn)行的,所以我們重點(diǎn)關(guān)注一下這個(gè)方法。prepareMethodOverride 這個(gè)方法主要用于獲取指定方法的方法數(shù)量 count,并根據(jù) count 的值進(jìn)行相應(yīng)的處理。count = 0 時(shí),表明方法不存在,此時(shí)拋出異常。count = 1 時(shí),設(shè)置 MethodOverride 對(duì)象的overloaded成員變量為 false。這樣做的目的在于,提前標(biāo)注名稱mo.getMethodName()的方法不存在重載,在使用 CGLIB 增強(qiáng)階段就不需要進(jìn)行校驗(yàn),直接找到某個(gè)方法進(jìn)行增強(qiáng)即可。

上面的方法沒(méi)太多的邏輯,比較簡(jiǎn)單,就先分析到這里。

2.2.2 bean 實(shí)例化前的后置處理

后置處理是 Spring 的一個(gè)拓展點(diǎn),用戶通過(guò)實(shí)現(xiàn) BeanPostProcessor 接口,并將實(shí)現(xiàn)類配置到 Spring 的配置文件中(或者使用注解),即可在 bean 初始化前后進(jìn)行自定義操作。關(guān)于后置處理較為詳細(xì)的說(shuō)明,可以參考我的了一篇文章Spring IOC 容器源碼分析系列文章導(dǎo)讀,這里就不贅述了。下面我們來(lái)看看 createBean 方法中的后置處理邏輯,如下:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    // 檢測(cè)是否解析過(guò),mbd.beforeInstantiationResolved 的值在下面的代碼中會(huì)被設(shè)置
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 應(yīng)用前置處理
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 應(yīng)用后置處理
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        // 設(shè)置 mbd.beforeInstantiationResolved
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        // InstantiationAwareBeanPostProcessor 一般在 Spring 框架內(nèi)部使用,不建議用戶直接使用
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // bean 初始化前置處理
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
       // bean 初始化后置處理
        result = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

在 resolveBeforeInstantiation 方法中,當(dāng)前置處理方法返回的 bean 不為空時(shí),后置處理才會(huì)被執(zhí)行。前置處理器是 InstantiationAwareBeanPostProcessor 類型的,該種類型的處理器一般用在 Spring 框架內(nèi)部,比如 AOP 模塊中的AbstractAutoProxyCreator抽象類間接實(shí)現(xiàn)了這個(gè)接口中的 postProcessBeforeInstantiation方法,所以 AOP 可以在這個(gè)方法中生成為目標(biāo)類的代理對(duì)象。不過(guò)我在調(diào)試的過(guò)程中,發(fā)現(xiàn) AOP 在此處生成代理對(duì)象是有條件的。一般情況下條件都不成立,也就不會(huì)在此處生成代理對(duì)象。至于這個(gè)條件為什么不成立,因 AOP 這一塊的源碼我還沒(méi)來(lái)得及看,所以暫時(shí)還無(wú)法解答。等我看過(guò) AOP 模塊的源碼后,我再來(lái)嘗試分析這個(gè)條件。

2.2.3 調(diào)用 doCreateBean 方法創(chuàng)建 bean

這一節(jié),我們來(lái)分析一下doCreateBean方法的源碼。在 Spring 中,做事情的方法基本上都是以do開(kāi)頭的,doCreateBean 也不例外。那下面我們就來(lái)看看這個(gè)方法都做了哪些事情。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    /* 
     * BeanWrapper 是一個(gè)基礎(chǔ)接口,由接口名可看出這個(gè)接口的實(shí)現(xiàn)類用于包裹 bean 實(shí)例。
     * 通過(guò) BeanWrapper 的實(shí)現(xiàn)類可以方便的設(shè)置/獲取 bean 實(shí)例的屬性
     */
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 從緩存中獲取 BeanWrapper,并清理相關(guān)記錄
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        /* 
         * 創(chuàng)建 bean 實(shí)例,并將實(shí)例包裹在 BeanWrapper 實(shí)現(xiàn)類對(duì)象中返回。createBeanInstance 
         * 中包含三種創(chuàng)建 bean 實(shí)例的方式:
         *   1. 通過(guò)工廠方法創(chuàng)建 bean 實(shí)例
         *   2. 通過(guò)構(gòu)造方法自動(dòng)注入(autowire by constructor)的方式創(chuàng)建 bean 實(shí)例
         *   3. 通過(guò)無(wú)參構(gòu)造方法方法創(chuàng)建 bean 實(shí)例
          *
         * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,則會(huì)使用 CGLIB 
         * 增強(qiáng) bean 實(shí)例。關(guān)于這個(gè)方法,后面會(huì)專門寫(xiě)一篇文章介紹,這里先說(shuō)這么多。
         */
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 此處的 bean 可以認(rèn)為是一個(gè)原始的 bean 實(shí)例,暫未填充屬性
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // 這里又遇到后置處理了,此處的后置處理是用于處理已“合并的 BeanDefinition”。關(guān)于這種后置處理器具體的實(shí)現(xiàn)細(xì)節(jié)就不深入理解了,大家有興趣可以自己去看
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    /*
     * earlySingletonExposure 是一個(gè)重要的變量,這里要說(shuō)明一下。該變量用于表示是否提前暴露
     * 單例 bean,用于解決循環(huán)依賴。earlySingletonExposure 由三個(gè)條件綜合而成,如下:
     *   條件1:mbd.isSingleton() - 表示 bean 是否是單例類型
     *   條件2:allowCircularReferences - 是否允許循環(huán)依賴
     *   條件3:isSingletonCurrentlyInCreation(beanName) - 當(dāng)前 bean 是否處于創(chuàng)建的狀態(tài)中
     * 
     * earlySingletonExposure = 條件1 && 條件2 && 條件3 
     *                        = 單例 && 是否允許循環(huán)依賴 && 是否存于創(chuàng)建狀態(tài)中。
     */
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean "" + beanName +
                    "" to allow for resolving potential circular references");
        }
        // 添加工廠對(duì)象到 singletonFactories 緩存中
        addSingletonFactory(beanName, new ObjectFactory() {
            @Override
            public Object getObject() throws BeansException {
                // 獲取早期 bean 的引用,如果 bean 中的方法被 AOP 切點(diǎn)所匹配到,此時(shí) AOP 相關(guān)邏輯會(huì)介入
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    Object exposedObject = bean;
    try {
        // 向 bean 實(shí)例中填充屬性,populateBean 方法也是一個(gè)很重要的方法,后面會(huì)專門寫(xiě)文章分析
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            /*
             * 進(jìn)行余下的初始化工作,詳細(xì)如下:
             * 1. 判斷 bean 是否實(shí)現(xiàn)了 BeanNameAware、BeanFactoryAware、
             *    BeanClassLoaderAware 等接口,并執(zhí)行接口方法
             * 2. 應(yīng)用 bean 初始化前置操作
             * 3. 如果 bean 實(shí)現(xiàn)了 InitializingBean 接口,則執(zhí)行 afterPropertiesSet 
             *    方法。如果用戶配置了 init-method,則調(diào)用相關(guān)方法執(zhí)行自定義初始化邏輯
             * 4. 應(yīng)用 bean 初始化后置操作
             * 
             * 另外,AOP 相關(guān)邏輯也會(huì)在該方法中織入切面邏輯,此時(shí)的 exposedObject 就變成了
             * 一個(gè)代理對(duì)象了
             */
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            // 若 initializeBean 方法未改變 exposedObject 的引用,則此處的條件為 true。
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            // 下面的邏輯我也沒(méi)完全搞懂,就不分析了。見(jiàn)諒。
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name "" + beanName + "" has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            ""getBeanNamesOfType" with the "allowEagerInit" flag turned off, for example.");
                }
            }
        }
    }

    try {
        // 注冊(cè)銷毀邏輯
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

上面的注釋比較多,分析的應(yīng)該比較詳細(xì)的。不過(guò)有一部分代碼我暫時(shí)沒(méi)看懂,就不分析了,見(jiàn)諒。下面我們來(lái)總結(jié)一下 doCreateBean 方法的執(zhí)行流程吧,如下:

從緩存中獲取 BeanWrapper 實(shí)現(xiàn)類對(duì)象,并清理相關(guān)記錄

若未命中緩存,則創(chuàng)建 bean 實(shí)例,并將實(shí)例包裹在 BeanWrapper 實(shí)現(xiàn)類對(duì)象中返回

應(yīng)用 MergedBeanDefinitionPostProcessor 后置處理器相關(guān)邏輯

根據(jù)條件決定是否提前暴露 bean 的早期引用(early reference),用于處理循環(huán)依賴問(wèn)題

調(diào)用 populateBean 方法向 bean 實(shí)例中填充屬性

調(diào)用 initializeBean 方法完成余下的初始化工作

注冊(cè)銷毀邏輯

doCreateBean 方法的流程比較復(fù)雜,步驟略多。由此也可了解到創(chuàng)建一個(gè) bean 還是很復(fù)雜的,這中間要做的事情繁多。比如填充屬性、對(duì) BeanPostProcessor 拓展點(diǎn)提供支持等。以上的步驟對(duì)應(yīng)的方法具體是怎樣實(shí)現(xiàn)的,本篇文章并不打算展開(kāi)分析。在后續(xù)的文章中,我會(huì)多帶帶寫(xiě)文章分析幾個(gè)邏輯比較復(fù)雜的步驟。有興趣的閱讀的朋友可以稍微等待一下,相關(guān)文章本周會(huì)陸續(xù)進(jìn)行更新。

3. 總結(jié)

到這里,createBean 方法及其所調(diào)用的方法的源碼就分析完了。總的來(lái)說(shuō),createBean 方法還是比較復(fù)雜的,需要多看幾遍才能理清一些頭緒。由于 createBean 方法比較復(fù)雜,對(duì)于以上的源碼分析,我并不能保證不出錯(cuò)。如果有寫(xiě)錯(cuò)的地方,還請(qǐng)大家指點(diǎn)迷津。畢竟當(dāng)局者迷,作為作者,我很難意識(shí)到哪里寫(xiě)的有問(wèn)題。

好了,本篇文章到此結(jié)束。謝謝閱讀。

參考

《Spring 源碼深度解析》- 郝佳

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


本作品采用知識(shí)共享署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際許可協(xié)議進(jìn)行許可。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/69639.html

相關(guān)文章

  • Spring專題之Bean初始化源碼分析(1)

    摘要:初始化我們知道容器初始化后會(huì)對(duì)容器中非懶加載的,單例的以及非抽象的定義進(jìn)行的初始化操作,所以我們分析源碼的入口也就是在容器初始化的入口,分析容器初始化后在什么地方開(kāi)始第一次的初始化。 前言 Spring IOC容器在初始化之后會(huì)對(duì)容器中非懶加載的,單例的以及非抽象的bean定義進(jìn)行bean的初始化操作,同時(shí)會(huì)也涉及到Bean的后置處理器以及DI(依賴注入)等行為。對(duì)于Bean的初始化,...

    harryhappy 評(píng)論0 收藏0
  • Spring IOC 容器源碼分析 - 獲取單例 bean

    摘要:簡(jiǎn)介為了寫(xiě)容器源碼分析系列的文章,我特地寫(xiě)了一篇容器的導(dǎo)讀文章。在做完必要的準(zhǔn)備工作后,從本文開(kāi)始,正式開(kāi)始進(jìn)入源碼分析的階段。從緩存中獲取單例。返回以上就是和兩個(gè)方法的分析。 1. 簡(jiǎn)介 為了寫(xiě) Spring IOC 容器源碼分析系列的文章,我特地寫(xiě)了一篇 Spring IOC 容器的導(dǎo)讀文章。在導(dǎo)讀一文中,我介紹了 Spring 的一些特性以及閱讀 Spring 源碼的一些建議。在...

    lufficc 評(píng)論0 收藏0
  • Spring IOC 容器源碼分析 - 余下初始化工作

    摘要:簡(jiǎn)介本篇文章是容器源碼分析系列文章的最后一篇文章,本篇文章所分析的對(duì)象是方法,該方法用于對(duì)已完成屬性填充的做最后的初始化工作。后置處理器是拓展點(diǎn)之一,通過(guò)實(shí)現(xiàn)后置處理器接口,我們就可以插手的初始化過(guò)程。 1. 簡(jiǎn)介 本篇文章是Spring IOC 容器源碼分析系列文章的最后一篇文章,本篇文章所分析的對(duì)象是 initializeBean 方法,該方法用于對(duì)已完成屬性填充的 bean 做最...

    Alfred 評(píng)論0 收藏0
  • Spring IOC 容器源碼分析系列文章導(dǎo)讀

    摘要:本文是容器源碼分析系列文章的第一篇文章,將會(huì)著重介紹的一些使用方法和特性,為后續(xù)的源碼分析文章做鋪墊。我們可以通過(guò)這兩個(gè)別名獲取到這個(gè)實(shí)例,比如下面的測(cè)試代碼測(cè)試結(jié)果如下本小節(jié),我們來(lái)了解一下這個(gè)特性。 1. 簡(jiǎn)介 Spring 是一個(gè)輕量級(jí)的企業(yè)級(jí)應(yīng)用開(kāi)發(fā)框架,于 2004 年由 Rod Johnson 發(fā)布了 1.0 版本。經(jīng)過(guò)十幾年的迭代,現(xiàn)在的 Spring 框架已經(jīng)非常成熟了...

    NSFish 評(píng)論0 收藏0
  • Spring IOC 容器源碼分析 - 循環(huán)依賴解決辦法

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

    aikin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

mochixuan

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<