spring源碼解析 -- 構(gòu)造bean

Spring源碼解析 -- 讀取bean元數(shù)據(jù)
spring源碼解析 -- 構(gòu)造bean
spring源碼解析 -- 注入屬性
spring源碼解析 -- Spring Context
Spring源碼解析 -- AOP原理(1)
Spring源碼解析 -- AOP原理(2)
Spring源碼解析 -- SpringMvc原理

源碼分析基于spring 4.3.x

前面文章已經(jīng)分析了spring如何加載xml配置中的bean元數(shù)據(jù),現(xiàn)在來分析一下spring構(gòu)造bean的過程。
關(guān)于閱讀源碼的思路,可參考 -- 如何閱讀java源碼

BeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("application.xml"));
Blog bean = (Blog)xmlBeanFactory.getBean("blog");

XmlBeanFactory的父類AbstractBeanFactory是spring中一個很重要的類,他為BeanFactory提供基礎(chǔ)服務(wù)。構(gòu)造bean就是由該類實(shí)現(xiàn)的。
AbstractBeanFactory#doGetBean

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

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

    Object sharedInstance = getSingleton(beanName); // #1
    if (sharedInstance != null && args == null) {
        ...
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  // #2
    }

    else {
        if (isPrototypeCurrentlyInCreation(beanName)) { // #3
            throw new BeanCurrentlyInCreationException(beanName);
        }

        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {   // #4
            ...
        }

        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);    // #5
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  // #6
            checkMergedBeanDefinition(mbd, beanName, args);

            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {    
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);   
                    try {
                        getBean(dep);   // #7
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {     // #8
                    try {
                        return createBean(beanName, mbd, args); // #9
                    }
                    catch (BeansException ex) {
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            ... 
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {   // #10
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

#1 單例的bean,先從緩沖中查詢
getSingleton方法會查詢
singletonObject,earlySingletonObjects,singletonFactories等緩存,它們都是簡單的map,緩存了單例的bean,正在創(chuàng)建的bean和ObjectFactory對象。

#2 如果構(gòu)造的bean是FactoryBean,進(jìn)行對應(yīng)的處理
getObjectForBeanInstance方法會根據(jù)參數(shù)beanInstance進(jìn)行處理,如果beanInstance是FactoryBean,會調(diào)用其getObject()方法創(chuàng)建bean,如果不是,返回直接返回該beanInstance參數(shù)。
FactoryBean是spring提供的一個擴(kuò)展接口,用戶實(shí)現(xiàn)該接口可以自定義bean的創(chuàng)建。

#3 如果現(xiàn)在正在創(chuàng)建這個bean,則直接報(bào)錯,這時(shí)很可能陷入循環(huán)引用了
#4 當(dāng)前BeanFactory不存在對應(yīng)的BeanDefinition,嘗試通過父BeanFactory構(gòu)造bean
#5 標(biāo)記這個bean正在構(gòu)造中
#6 獲取BeanDefinition
前面解析spring加載bean數(shù)據(jù)的文章中說過,spring會將bean元數(shù)據(jù)轉(zhuǎn)化為BeanDefinition,存入DefaultListableBeanFactory#beanDefinitionMap屬性中。
getMergedLocalBeanDefinition方法會獲取對應(yīng)BeanDefinition,如果BeanDefinition存在ParentName,會獲取父BeanDefinition,再合并元數(shù)據(jù)。

#7 先構(gòu)造依賴的bean
#8 使用ObjectFactory構(gòu)造并注冊一個bean,getSingleton方法也要完成構(gòu)造bean的準(zhǔn)備和善后工作。
#9 匿名的ObjectFactory,調(diào)用AbstractAutowireCapableBeanFactory#createBean進(jìn)行實(shí)際的構(gòu)造bean工作
#10 bean類型轉(zhuǎn)換

spring中bean有singleton,prototype等范圍,這里只關(guān)注singleton類型的bean的構(gòu)造過程。

#8步驟,DefaultSingletonBeanRegistry#getSingleton(注意getSingleton有重載方法)

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                ...
                beforeSingletonCreation(beanName);  // #1
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    singletonObject = singletonFactory.getObject(); // #2
                    newSingleton = true;
                }
                ...
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);    // #3
                }
            }
            return singletonObject;
        }
    }

#1 僅做錯誤檢查,也是提供給子類的擴(kuò)展方法
#2 真正構(gòu)造bean的方法,調(diào)用AbstractBeanFactory#doGetBean方法#9步驟的匿名類處理,實(shí)際調(diào)用AbstractAutowireCapableBeanFactory#createBean
#3 單例的bean,加入緩沖中

真正的構(gòu)造bean方法
AbstractAutowireCapableBeanFactory#createBean

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

    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);   // #1
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    try {
        mbdToUse.prepareMethodOverrides();  // #2
    }
    ...

    try {
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);   // #3
        if (bean != null) {
            return bean;
        }
    }
    ...

    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);   // #4
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    ...
}

#1 確保jdk已加載bean的class
#2 對bean的lookup-method和replace-method做檢查工作
#3 spring的擴(kuò)展機(jī)制,調(diào)用BeanPostProcessor#postProcessBeforeInstantiation方法,
注意,如果resolveBeforeInstantiation返回非null對象,這里將直接返回該對象作為bean,spring不再構(gòu)造該bean。
#4 繼續(xù)構(gòu)造bean

AbstractAutowireCapableBeanFactory#doCreateBean

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

    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);   // #1
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);  // #2
    }
    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);   // #3
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    ...

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);   // #4
        exposedObject = initializeBean(beanName, exposedObject, mbd);   // #5
    }
    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);
        }
    }

    ...

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

    return exposedObject;
}

#1 查詢BeanWrapper緩沖
#2 構(gòu)造一個空的(屬性未注入)bean,生成BeanWrapper
#3 spring擴(kuò)展機(jī)制,調(diào)用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
#4 populateBean負(fù)責(zé)注入屬性到bean中,后面有對應(yīng)文章解析該步驟
#5 spring擴(kuò)展機(jī)制,調(diào)用Aware方法和init方法,并調(diào)用BeanPostProcessor#postProcessAfterInitialization方法。
#6 如果bean存在Destroy方法,或存在對應(yīng)的DestructionAwareBeanPostProcessor,注冊該bean為disposable。(該bean銷毀時(shí)要調(diào)用對應(yīng)的銷毀機(jī)制)

這里涉及到循環(huán)引用的處理,比較繁瑣,所以省略了很多代碼,只保留bean創(chuàng)建相關(guān)的代碼。

BeanWrapper是對bean的包裝類,提供了對bean的class,property進(jìn)行操作的方法。

#2步驟,AbstractAutowireCapableBeanFactory#createBeanInstance

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        Class<?> beanClass = resolveBeanClass(mbd, beanName);   // #1

        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());
        }

        if (mbd.getFactoryMethodName() != null)  {  // #2
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {   // #3
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) { 
            if (autowireNecessary) {
                return autowireConstructor(beanName, mbd, null, null);  // #4
            }
            else {
                return instantiateBean(beanName, mbd);  // #5
            }
        }

        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  // #6
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        return instantiateBean(beanName, mbd);
    }


#1 獲取bean的class
#2 如果存在factoryMethod,通過factoryMethod構(gòu)造bean
#3 判斷該class已經(jīng)構(gòu)造過bean了
#4 使用之前選擇好的構(gòu)造函數(shù)構(gòu)造bean
#5 使用無參構(gòu)造函數(shù)構(gòu)造bean
#6 spring根據(jù)構(gòu)造函數(shù)的參數(shù),自行選擇構(gòu)造函數(shù),邏輯較復(fù)雜。

下面看看使用無參構(gòu)造方法構(gòu)造bean,AbstractAutowireCapableBeanFactory#instantiateBean -> SimpleInstantiationStrategy#instantiate

public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
        if (bd.getMethodOverrides().isEmpty()) {
            Constructor<?> constructorToUse;
            synchronized (bd.constructorArgumentLock) {
                constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {
                    final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                        if (System.getSecurityManager() != null) {
                            ...
                        }
                        else {
                            constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);   // #1
                        }
                        bd.resolvedConstructorOrFactoryMethod = constructorToUse;   // #2
                    }
                    catch (Throwable ex) {
                        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
                }
            }
            return BeanUtils.instantiateClass(constructorToUse);    // #3
        }
        else {
            return instantiateWithMethodInjection(bd, beanName, owner);     // #4
        }
    }

#1 獲取無參構(gòu)造函數(shù)
#2 添加無參構(gòu)造函數(shù)加入到BeanDefinition緩存中
#2 BeanUtils#instantiateClass通過構(gòu)造函數(shù)構(gòu)造bean
#3 bean中存在lookup-method或replace-method,必須使用CGLIB構(gòu)造bean

到這里,bean已經(jīng)構(gòu)造完成,下一步就是注入屬性了。

如果您覺得本文不錯,歡迎關(guān)注我的微信公眾號,您的關(guān)注是我堅(jiān)持的動力!


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容