由Spring框架中的單例模式想到的

單例模式是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例的特殊類。通過單例模式可以保證系統中一個類只有一個實例

注:Spring源碼的版本4.3.4

Spring依賴注入Bean實例默認是單例的,我們由此展開。

Spring的依賴注入(包括lazy-init方式)都是發生在AbstractBeanFactorygetBean裏。getBean的doGetBean方法調用getSingleton進行bean的創建。lazy-init方式,在容器初始化時候進行調用,非lazy-init方式,在用戶向容器第一次索要bean時進行調用

同步線程安全的單例核心代碼:

/**
     * Return the (raw) singleton object registered under the given name.
     * <p>Checks already instantiated singletons and also allows for an early
     * reference to a currently created singleton (resolving a circular reference).
     * @param beanName the name of the bean to look for
     * @param allowEarlyReference whether early references should be created or not
     * @return the registered singleton object, or {@code null} if none found
     */
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

從上面代碼可以看到,spring依賴注入時,使用了雙重判斷加鎖的單例模式,首先從緩存中獲取bean實例,如果爲null,對緩存map加鎖,然後再從緩存中獲取bean,如果繼續爲null,就創建一個bean。這樣雙重判斷,能夠避免在加鎖的瞬間,有其他依賴注入引發bean實例的創建,從而造成重複創建的結果。

在這裏Spring並沒有使用私有構造方法來創建bean,而是通過singletonFactory.getObject()返回具體beanName對應的ObjectFactory來創建bean。我們一路跟蹤下去,發現實際上是調用了AbstractAutowireCapableBeanFactorydoCreateBean方法,返回了BeanWrapper包裝並創建的bean實例。

ObjectFactory主要檢查是否有用戶定義的BeanPostProcessor後處理內容,並在創建bean時進行處理,如果沒有,就直接返回bean本身)

見如下代碼:

534行創建bean實例返回給BeanWrapper

563行addSingletonFactory增加beanNameObjectFactory的鍵值對應關係。
這裏寫圖片描述
這裏寫圖片描述

    /**
     * Actually create the specified bean. Pre-creation processing has already happened
     * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
     * <p>Differentiates between default bean instantiation, use of a
     * factory method, and autowiring a constructor.
     * @param beanName the name of the bean
     * @param mbd the merged bean definition for the bean
     * @param args explicit arguments to use for constructor or factory method invocation
     * @return a new instance of the bean
     * @throws BeanCreationException if the bean could not be created
     * @see #instantiateBean
     * @see #instantiateUsingFactoryMethod
     * @see #autowireConstructor
     */
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

        // Allow post-processors to modify the merged bean definition.
        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;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        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");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

getEarlyBeanReference獲取bean的所有後處理器,並進行處理。如果是SmartInstantiationAwareBeanPostProcessor類型,就進行處理,如果沒有相關處理內容,就返回默認的實現。

   /**
     * Obtain a reference for early access to the specified bean,
     * typically for the purpose of resolving a circular reference.
     * @param beanName the name of the bean (for error handling purposes)
     * @param mbd the merged bean definition for the bean
     * @param bean the raw bean instance
     * @return the object to expose as bean reference
     */
    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                    if (exposedObject == null) {
                        return null;
                    }
                }
            }
        }
        return exposedObject;
    }

原地址:http://www.cnblogs.com/chengxuyuanzhilu/p/6404991.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章