Spring源码浅析之Bean的创建(后篇)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ljw761123096/article/details/80449810

在前篇中我们已经对Spring容器中的AbstractBeanFactory类作了简单的介绍。当Spring容器使用BeanFactory获取单例bean时,会从缓存中获取已经注册的bean实例,如果还未注册会创建该bean实例。对于原型bean,Spring容器总是会创建一个新的bean实例。
在本篇中我们将对AbstractBeanFactory类中createBean方法做简单的分析。在AbstractBeanFactory类中该方法是一个抽象方法,它由AbstractBeanFactory的子类AbstractAutowireCapableBeanFactory实现。我们来看看该类和其中的createBean方法。

AbstractAutowireCapableBeanFactory
我们先来看一下AbstractBeanFactory的实现类们:
这里写图片描述
其中XmlBeanFactory类在Spring3.1后已经被摒弃,DefaultListableBeanFactory类是ListableBeanFactory接口和BeanDefinitionRegistry接口的默认实现类,也是Spring容器中核心的BeanFactory之一。
我们主要看AbstractAutowireCapableBeanFactory类,它主要实现了bean的创建、属性注入、初始化等功能,它的核心方法是createBean和doCreateBean方法。

createBean
AbstractAutowireCapableBeanFactory类中的createBean方法是对AbstractBeanFactory类中的createBean抽象方法的实现。具体源码如下(简化日志输出):

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

        // 获取BeanDefinition(省略创建的日志)
        RootBeanDefinition mbdToUse = mbd;

        // 确保bean的Class类型已经被解析
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        // 如果bean的类型是动态的,则拷贝bean的BeanDefinition
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // 验证和准备BeanDefinition中的重写方法
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // before-instantiation处理,在实例化之前检查是否有代理类可以返回
            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);
        }

        try {
            // 实际的创建方法
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            // 省略正在创建的日志输出
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // 先前在创建bean的创建上下文时已经检测到异常,或者将非法singleton状态传递给DefaultSingletonBeanRegistry。
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

从上面的代码中我们可以看到,createBean在创建bean时首先会检查bean的类型是否已经被正确的解析,并对动态类型的bean作特殊处理。然后会尝试获取目标bean的代理类,最后再进行实际的创建工作。

doCreateBean
接下来我们看看最重要的doCreateBean方法到底干了哪些事,代码如下(省略日志输出):

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

        /// 实例化bean,并用wrapper包装
        BeanWrapper instanceWrapper = null;
        // 从实例缓存中获取
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        // 缓存中没有则实例化
        if (instanceWrapper == null) {
            // 实际的实例化操作
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 获取实例化后的bean实例
        final Object bean = instanceWrapper.getWrappedInstance();
        // 获取bean的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        // 类型不为空则注入到BeanDefinition中的解析类型中
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // 对MergedBeanDefinition进行PostProcessors处理,该处理可以允许在bean实例化后对bean的BeanDefinition进行修改
        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);
                }
                // 已处理标志为true
                mbd.postProcessed = true;
            }
        }

        // 判断是否要提前暴露
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        // 如果要
        if (earlySingletonExposure) {
            // 省略提前引用的日志
            // 添加可以获取提前引用的单例工厂
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // 初始化bean实例
        Object exposedObject = bean;
        try {
            // 属性注入
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化bean(setBeanName,setBeanClassLoader等)
            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);
            }
        }
        // 如果要提前暴露单例bean
        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            // 能获取到
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                // 检查依赖该bean的bean还都不存在(正常情况应该还不存在)
                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不对或不是最终版本)
                    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.");
                    }
                }
            }
        }

        // 尝试注册disposable的bean(即destroy方法)
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }
        // 返回创建完成的bean
        return exposedObject;
    }

从上面的代码中,我们可以看到doCreateBean方法主要做了以下两件事:
1.实际的完成了bean的实例化,属性的注入和初始化操作,并尝试注册可注销的bean。
2.针对允许提前引用的情况,对bean做提前暴露的操作。
populateBean方法能对实例化后的bean的属性进行注入。
initializeBean方法能对实现了BeanNameAware,BeanClassLoaderAware和BeanFactoryAware接口的bean的name,classLoader和factory实现注入。这三个接口与Spring容器中bean生命周期的前三个部分相对应。并且在初始化之前和初始化之后都会调用相应的BeanPostProcessor。这里不再累述。

总结
通过上述源码,我们大致可以看出Spring容器中bean的实际创建过程,以及bean的提前暴露以解决循环引用问题的整个逻辑。
结合前篇,我们可以看到,AbstractAutowireCapableBeanFactory类与AbstractBeanFactory类通过getBean和createBean方法,实现了Spring容器创建和获取bean的大部分逻辑。在以后的博客中,我可能会对还有一个重要步骤,即Spring容器如何注册bean进行一下简单的介绍。

阅读更多
换一批

没有更多推荐了,返回首页