Spring 


doCreateBean方法與
BeanWrapper對象

悄悄拔尖,而後驚豔全部人.期待與你一塊兒進步.java

1.萬衆期待的 doCreateBean

  今天這篇文章,開始分析在Spring中doCreateBean()方法。上一篇文章中提到的createBean()方法的一個子方法:spring

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


    // BeanWrapper 是用來持有建立出來的Bean對象
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 若是是singleton,先清除緩存中同名的Bean
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        /* * 經過createBeanInstance 來完成Bean所包含的java對象的建立。 * 對象的生成有不少種不一樣的方式,能夠經過工廠方法生成, * 也能夠經過容器的autowire特性生成,這些生成方式都是由BeanDefinition來指定的 */
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    /* getWrappedInstance() 得到原生對象*/
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }


    // 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;
        }
    }


    /* * 是否須要提早曝光:單例 & 容許循環依賴& 當前的bean正在建立中,檢測循環依賴 */
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        /* * setter 方法注入的Bean,經過提早暴露一個單例工廠方法 * 從而可以使其餘Bean引用到該Bean,注意經過setter方法注入的 * Bean 必須是單例的纔會到這裏來。 * 對 Bean 再一次依賴引用,主要應用 SmartInstantiationAwareBeanPostProcessor * 其中 AOP 就是在這裏將advice動態織入bean中,若沒有則直接返回,不作任何處理 * * 在Spring中解決循環依賴的方法: * 在 B 中建立依賴 A 時經過 ObjectFactory 提供的實例化方法來中斷 A 中的屬性填充, * 使 B 中持有的 A 僅僅是剛初始化並無填充任何屬性的 A,初始化 A 的步驟是在最開始建立A的時候進行的, * 可是 由於 A 與 B 中的 A 所表示的屬性地址是同樣的,因此在A中建立好的屬性填充天然能夠經過B中的A獲取, * 這樣就解決了循環依賴。 */
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }


    // Initialize the bean instance.
    /* * 將原生對象複製一份 到 exposedObject,這個exposedObject在初始化完成處理以後 * 會做爲依賴注入完成後的Bean */
    Object exposedObject = bean;
    try {
        /* Bean的依賴關係處理過程*/
        populateBean(beanName, mbd, instanceWrapper);
        /* 將原生對象變成代理對象*/
        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) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    // 檢測循環依賴
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                /* * 由於Bean建立後其所依賴的Bean必定是已經建立的, * actualDependentBeans 不爲空則表示當前bean建立後其依賴的Bean卻沒有所有建立完, * 也就是說存在循環依賴 */
                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.");
                }
            }
        }
    }


    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }


    return exposedObject;
}
複製代碼

  簡單概括上述方法都完成了什麼事:數組

  • ①:若是是單例首先須要清除緩存
  • ②:實例化 bean,將 BeanDefinition 轉化爲 BeanWrapper
  • ③:MergedBeanDefinitionPostProcessor 的應用
  • ④:依賴處理
  • ⑤:屬性填充
  • ⑥:循環依賴處理
  • ⑦:註冊 DisposableBean
  • ⑧:完成建立並返回

  isSingletonCurrentlyInCreation(beanName)在這裏返回的時候爲true。還記得在什麼地方,將當前正在建立的beanName放入到 singletonsCurrentlyInCreation這個Set 集合中嗎?緩存

答案就是: getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法中的 beforeSingletonCreation(beanName)方法中 app

addsingletonsCurrentlyInCreation
  在這裏須要指出 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 這一行代碼在Spring中解決循環依賴起着很是重要的做用。其原理就是,提早暴露 ObjectFactory 將其添加到 singletonFactories中去,而後經過 getObject()返回對象。

2.建立bean

  在今天這篇文章中,還將介紹建立 createBeanInstance() 返回 BeanWrapper 對象的入口,由於在Spring中建立對象的方式作了區分, 分爲經過: 使用工廠方法對Bean進行實例化、經過構造方法自動裝配的方式構造Bean對象、經過默認的無參構造方法進行實例化。每一種方式都有對應的方法進行處理。這裏是完成 BeanWrapper建立的地方:ide

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    /** 確認須要實例化的bean */
    Class<?> beanClass = resolveBeanClass(mbd, beanName);


    /** * 檢查一個類的訪問權限,spring默認狀況下,對於非public的類是容許訪問的 */
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }


    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }


    /** 使用工廠方法對Bean進行實例化*/
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }


    /** * 屢次構建同一個Bean時,可使用shortcut */
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                // 若是已經解析了構造方法的參數,就必須經過一個帶參數的構造方法來實例
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        if (autowireNecessary) {
            // 經過構造方法自動裝配的方式構造Bean對象
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            // 經過默認的無參構造方法進行實例化
            return instantiateBean(beanName, mbd);
        }
    }


    // Candidate constructors for autowiring?
    /** * 使用構造函數進行實例化 * 由後置處理器決定返回使用的構造方法 * 當有多個構造器的時候,Spring 認爲是沒有經過構造器實例化的 */
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }


    // Preferred constructors for default construction?


    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }


    // No special handling: simply use no-arg constructor.
    /** 使用默認的構造函數*/
    return instantiateBean(beanName, mbd);
}
複製代碼

  在上述方法中經過 determineConstructorsFromBeanPostProcessors()方法來肯定使用哪一個構造器來完成初始化。這裏要注意的就是,當咱們的類裏面有多個構造器的時候,Spring認爲是沒有構造器使用的。這一部分的詳細解釋會在後面的文章,裏面在作討論。函數

3.BeanWrapper 對象

  這個方法返回主要是用來返回 BeanWrapper 對象。我本身對 BeanWrapper 的理解就是 Bean包裝。Spring提供的一個用來操 作javaBean屬性的工具,使用它能夠直接修改一個對象的屬性。BeanWrapper自己是一個接口,它提供了一整套處理Bean的方法,代碼以下:工具

public interface BeanWrapper extends ConfigurablePropertyAccessor {


	/** * 爲數組和集合自動增加指定一個限制。在普通的BeanWrapper上默認是無限的。 */
	void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);


	/** * 返回數組和集合自動增加的限制。 */
	int getAutoGrowCollectionLimit();


	/** * 返回對象包裝的bean實例 */
	Object getWrappedInstance();


	/** * 返回被包裝的Bean對象的類型。 */
	Class<?> getWrappedClass();


	/** * 獲取包裝對象的PropertyDescriptors */
	PropertyDescriptor[] getPropertyDescriptors();


	/** * 獲取包裝對象的特定屬性的屬性描述符。 */
	PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;


}


複製代碼

  這個 BeanWrapper 在Spring中是對Bean實力化來講一個很是重要的對象,在進行依賴關係處理的時候會使用到該對象,關於依賴對象的注入,後面會有專門的文章分析。post

相關文章
相關標籤/搜索