Spring4.3.x 容器中bean的創建過程(1)——走進初始化bean的主要戰場

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/chyohn/article/details/54967539

概述

spring創建bean時需要一個重要的對象,那就是BeanDefinition對象,spring在創建BeanFactory時會把xml配置文件和註解信息轉換爲一個個BeanDefinition對象,BeanDefinition對象存儲的是單個bean的配置信息,比如依賴類、scope、是否延遲加載等等,對於BeanDefinition的創建過程,可以閱讀我的Spring4.3.x 淺析xml配置的解析過程系列,如
把<bean>標籤轉換成BeanDefinition對象
解析context命名空間之annotation-config標籤
解析context命名空間之component-scan標籤
解析aop命名空間之config標籤
解析aop命名空間之aspectj-autoproxy標籤

拿到BeanDefinition對象和一切準備工作完成後,Spring就開始根據BeanDefinition對象創建第一的bean。那Spring容器是怎麼創建bean的呢?這就是這篇文章討論的內容。

在spring容器的初始化過程中,BeanFactory對象創建完成後,容器就會創建並執行bean工廠後處理器對象,然後在註冊Bean後處理器時會創建Bean後處理器對象,初始化消息資源時會創建MessageSource對象,初始化事件傳播器時會創建ApplicationEventMulticaster對象。前面所有應用內部級的對象創建完成後,容器纔會初始化所有業務級的非延遲加載單例對象。關於spring容器的初始化過程見Spring4.3.x 容器的刷新過程,下面從spring容器創建非延遲加載單例對象來探討bean的創建過程。

創建bean的過程

Spring容器在刷新過程中以AbstractApplicationContext的finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)方法爲初始化容器中所有非延遲加載單例bean的入口,這個方法的源碼如下。

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 初始化ConversionService
        // 在ConfigurableApplicationContext接口中聲明:String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // 註冊一個默認的內部value解析器
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
                @Override
                public String resolveStringValue(String strVal) {
                    return getEnvironment().resolvePlaceholders(strVal);
                }
            });
        }

        // 初始化LoadTimeWeaverAware對象來支持註冊他們的transformers
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // 停止使用臨時類加載器來做類型匹配
        beanFactory.setTempClassLoader(null);

        // 允許緩存所有的bean元數據定義,不希望今後再更改工廠的配置
        beanFactory.freezeConfiguration();

        // 初始化所有非延遲單例bean
        beanFactory.preInstantiateSingletons();
    }

finishBeanFactoryInitialization方法中創建bean的代碼是最後一句,調用ConfigurableListableBeanFactory接口的preInstantiateSingletons()方法,這個方法的實現代碼在DefaultListableBeanFactory類中,源碼如下。

    @Override
    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        // 複製一份Bean名稱
        List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

        // 觸發所有非延遲加載單例bean的初始化
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    // 獲取FactoryBean對象
                    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit; // 標識FactoryBean是否需要馬上初始化Bean
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            @Override
                            public Boolean run() {
                                return ((SmartFactoryBean<?>) factory).isEagerInit();
                            }
                        }, getAccessControlContext());
                    } else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        // 創建Bean
                        getBean(beanName);
                    }
                } else {
                    // 創建Bean
                    getBean(beanName);
                }
            }
        }

        for (String beanName : beanNames) {
            // 獲取指定的Bean,此步驟會使用BeanFacotry對象獲取對應的Bean
            Object singletonInstance = getSingleton(beanName);
            // 觸發所有SmartInitializingSingleton對象的afterSingletonsInstantiated()方法
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged(new PrivilegedAction<Object>() {
                        @Override
                        public Object run() {
                            smartSingleton.afterSingletonsInstantiated();
                            return null;
                        }
                    }, getAccessControlContext());
                } else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

preInstantiateSingletons()方法調用BeanFactory接口的getBean(String name)方法來創建Bean,此方法的實現代碼在AbstractBeanFacotry中,源碼如下。

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

這裏簡單說一下BeanFactory的5個getBean重載方法的實現最終都是調用AbstractBeanFacotry類的doGetBean方法,它有4個參數,第一個參數爲字符串類型的name參數,可以是bean的ID或者別名;第二個參數爲Class類型的requiredType參數,指定需要獲取的Bean的類型;第三個參數爲Object數組的args參數,用於指定構造方法的參數;第四個參數爲布爾類型的typeCheckOnly,true表示只做類型檢查,false不僅要檢查類型,還要把bean標識爲已創建。這個方法的源碼如下。

    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        // 首先從singleton緩存中查找手動註冊的單例對象
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            // 返回sharedInstance自身
            // 如果sharedInstance爲FactoryBean對象,則返回它所創建的Bean實例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else {
            // 檢查beanName是否指向的是一個正在創建的prototype對象,是則拋出異常
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 檢查當前BeanFacotry中是否存在對應的BeanDefintion對象
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 不存在,則從父BeanFactory中獲取Bean
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // 根據指定的構造器參數創建Bean
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                } else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                // 把bean標識爲已創建
                markBeanAsCreated(beanName);
            }

            try {
                // 獲取RootBeanDefinition對象
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 檢查BeanDefintion是否合格,如果它代表的是一個抽象類,則拋出異常
                checkMergedBeanDefinition(mbd, beanName, args);

                // 獲取bean所依賴的bean
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    // 初始化所有依賴的Bean
                    for (String dependsOnBean : dependsOn) {
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean);
                    }
                }

                // 創建Bean實例
                if (mbd.isSingleton()) {
                    // 創建單例bean
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                // 創建Bean
                                return createBean(beanName, mbd, args);
                            } catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    // bean爲prototype,創建新的實例
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        // 創建bean
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    // 創建其它作用域的Bean
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                beforePrototypeCreation(beanName);
                                try {
                                    // 創建bean
                                    return createBean(beanName, mbd, args);
                                }
                                finally {
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            } catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // 檢查創建好的Bean實例的類型是否與requiredType匹配
        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                // 如果不匹配則進行類型轉換
                return getTypeConverter().convertIfNecessary(bean, requiredType);
            } catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type [" +
                            ClassUtils.getQualifiedName(requiredType) + "]", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

在doGetBean方法中,不管是哪種作用域的Bean,都會調用createBean方法來創建Bean實例,createBean方法在AbstractBeanFactory中被定義爲抽象方法,它的實現在AbstractAutowireCapableBeanFactory類中,源碼如下。

    @Override
    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對象
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        try {
            // 準備方法重寫,這個是通過<lookup-method>標籤定義的
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // 執行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法返回一個代理對象
            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);
        }

        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }

AbstractAutowireCapableBeanFactoryd的createBean會調用resolveBeforeInstantiation方法來執行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,如果這個方法返回的bean不爲null,則bean創建完成。否則將調用看AbstractAutowireCapableBeanFactory類的doCreateBean方法創建bean的,doCreateBean方法的源碼如下。

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        // 初始化bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 創建Bean實例,並返回其包裝器
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

        // 到這一步,Bean已經實例化完成,但還沒定製bean的屬性
        // 此時,執行MergedBeanDefinitionPostProcessor對象的postProcessMergedBeanDefinition方法
        // 比如處理@Autowired、@Value等註解
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }

        // 爲了解決bean之間的循環引用,需要提前緩存單例的Bean的引用
        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");
            }
            // 爲單例bean添加ObjectFactory對象
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    // 此處將執行SmartInstantiationAwareBeanPostProcessor後處理器的getEarlyBeanReference方法
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // 初始化bean的
        Object exposedObject = bean;
        try {
            // 設置bean的屬性值
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                // 調用bean後處理器以及InitializingBean的afterPropertiesSet方法
                // =>和init-method方法
                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) {
            // 獲得單例bean
            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<String>(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 {
            // 如果bean需要在工廠關閉前被銷燬,則註冊bean
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        } catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

doCreateBean方法是實例化和初始化bean的戰場,它調用createBeanInstance方法創建bean的實例和BeanWrapper對象;調用populateBean方法設置bean的屬性;調用initializeBean方法執行Bean後處理器和InitializingBean對象的afterPropertiesSet方法以及init-method方法;最後調用registerDisposableBeanIfNecessary方法註冊bean的銷燬方法。

總結

(1)不管是什麼作用域的bean,都會通過AbstractAutowireCapableBeanFactory類的doCreateBean方法來創建。doCreateBean方法是創建bean的主要戰場。

(2)只要調用BeanFactory對象的任意一個getBean方法都會觸發bean的創建,BeanFactory接口提供了5個getBean重載方法。

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