天天看點

SpringIoc源碼(十六)- BeanFactory(五)- getBean(doGetBean下 - doCreateBean前的準備工作)

目錄

1、getSingleton

2、createBean

1)、擷取真正的Class類型

2)、初始化真正使用的RootBeanDefinition

3)、lookup-method和replace-method的處理

4)、InstantiationAwareBeanPostProcessor處理(resolveBeforeInstantiation)

5)、doCreateBean(真正的建立)

    繼續AbstractBeanFactory的doGetBean分析,主要分析是5、6步驟:

    1、判斷是否正在建立中

    2、判斷父BeanFactory是否存在(一般都不存在,是以不分析了)

    3、調用getMergedLocalBeanDefinition方法擷取BeanDefinition,并且調用checkMergedBeanDefinition方法驗證    

    4、擷取BeanDefinition#getDependsOn,有依賴則周遊,遞歸調用getBean

    5、根據BeanDefinition的scope按照單利、原型。其他類型進行初始化(目前隻考慮單利類型)

    6、過調用的是getBean(A.class)類型,則需要進行轉換

單利類型的初始化過程如下:

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
           

    與一篇部落格的緩存中擷取一樣,先getSingleton,再getObjectForBeanInstance,因為目前不知道需要擷取的是FactoryBean本身,還是FactoryBean#getObject,還是正常的Bean。主要的方法依賴于createBean初始化之後,getSingleton根據情況傳回。

1、getSingleton

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        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 + "'");
            }
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                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;
                }
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}
           

    在createBean完成後,會調用DefaultSingletonBeanRegistry的getSingleton方法傳回Bean對象。

1、在createBean調用完後new 了Bean的抽象工廠,還是用synchronized鎖住singletonObjects,當然第一次擷取到的還是null

2、判斷是否正在建立中

3、beforeSingletonCreation做一些判斷

4、核心方法是singletonFactory.getObject();擷取到單利的Bean

5、afterSingletonCreation做一些判斷

6、調用addSingleton方法放入緩存中下次就能直接擷取了(這裡鎖了兩次singletonObjects對象)

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}
           

2、createBean

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    // 省略try catch的代碼部分,友善清晰的看過程
    RootBeanDefinition mbdToUse = mbd;
    // 擷取真正的Class
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }
    // 對Spring定義的lookup-method和replace-method的處理
    mbdToUse.prepareMethodOverrides();
   // 初始化前的InstantiationAwareBeanPostProcessor處理器(可能在這裡傳回對象)
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
        return bean;
    }
    // 在InstantiationAwareBeanPostProcessor沒有擷取到對象,則走正常建立過程(這才是真正的初始化過程)
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    return beanInstance;
}
           

1)、擷取真正的Class類型

protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, 
    final Class<?>... typesToMatch) throws CannotLoadBeanClassException {
    // 省略try catch部分的代碼
    if (mbd.hasBeanClass()) {
        return mbd.getBeanClass();
    }
    if (System.getSecurityManager() != null) {
        return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
                doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
    }
    else {
        return doResolveBeanClass(mbd, typesToMatch);
    } 
}
           

    很多時候RootBeanDefinition沒有設定beanClass,則需要解析對應的Class(設定了直接傳回)。後面分析該過程。

2)、初始化真正使用的RootBeanDefinition

    上面解析的Class如果不為null,則需要初始化一個RootBeanDefinition,并将該Class設定進去,否則就使用傳入的RootBeanDefinition即可。

3)、lookup-method和replace-method的處理

    對lookup-method和replace-method類型的标記處理而已

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    if (hasMethodOverrides()) {
        getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
    }
}
           
protected void prepareMethodOverride(MethodOverride mo) 
    throws BeanDefinitionValidationException {

    int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
    if (count == 0) {
        throw new BeanDefinitionValidationException("省略");
    } else if (count == 1) {
        // Mark override as not overloaded, to avoid the overhead of arg type checking.
        mo.setOverloaded(false);
    }
}
           

4)、InstantiationAwareBeanPostProcessor處理(resolveBeforeInstantiation)

     在真正的doCreateBean之前允許InstantiationAwareBeanPostProcessor類型的BeanPostProcess,調用postProcessBeforeInstantiation方法。也可以了解,Spring不僅允許FactoryBean的getObject類型初始化Bean,還允許InstantiationAwareBeanPostProcessor傳回Bean。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}
           

    applyBeanPostProcessorsBeforeInstantiation方法如下:

@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}
           

    如果InstantiationAwareBeanPostProcessor處理(傳回)過該Class類型的Bean,那麼該Bean就沒有走正常bean的生命周期(詳細可以參見:Spring-Bean的作用域和生命周期),那麼允許其調用一次BeanPostProcess的後置處理方法postProcessAfterInitialization,前置處理方法是修改Bean資訊的,是以這裡沒必要回調前置方法了。就拿到所有的BeanPostProcess周遊回調即可,如下:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, 
    String beanName) throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
           

5)、doCreateBean(真正的建立)

    完整的Bean的生命周期都會在這裡完成,也是最複雜的過程。next專門進行分析。

繼續閱讀