Spring IOC容器创建bean过程浅析

1. 背景

Spring框架本身非常庞大,源码阅读可以从Spring IOC容器的实现开始一点点了解。然而即便是IOC容器,代码仍然是非常多,短时间内全部精读完并不现实
本文分析比较浅,而完整的IOC创建bean实际上是非常复杂的。本文对于BeanDefinition的加载解析,bean实例化的反射调用细节不作介绍,仅以较为粗略的角度来大体感受IOC容器创建bean的过程。

本文涉及的Spring源码版本为4.3.5.RELEASE。

2. 想要了解什么

下面就抛出几个想要了解的问题,也是本文介绍所要围绕的关键点。

  • BeanFactory和ApplicationContext的区别
  • IOC容器创建Bean的大致过程
  • Bean的循环依赖是如何解决的
  • 那些Aware究竟是什么

3. 从源码中找出问题的答案

3.1 BeanFactory & ApplicationContext

3.1.1 BeanFactory体系

org.springframework.beans.factory.BeanFactory是Spring的Bean容器的一个非常基本的接口,位于spring-beans模块。它包括了各种getBean方法,如通过名称、类型、参数等,试图从Bean容器中返回一个Bean实例。还包括诸如containsBean, isSingleton, isPrototype等方法判断Bean容器中是否存在某个Bean或是判断Bean是否为单例/原型等等。


可以看到BeanFactory向下主要有三条继承路线

  • ListableBeanFactory
    在BeanFactory基础上,支持对Bean容器中Bean的枚举。
  • HierarchicalBeanFactory -> ConfigurableBeanFactory
    HierarchicalBeanFactory有个getParentBeanFactory方法,使得Bean容器具有亲缘关系。而ConfigurableBeanFactory则是对BeanFactory的一系列配置功能提供了支持。
  • AutowireCapableBeanFactory
    提供了一系列用于自动装配Bean的方法,用户代码比较少用到,更多是作为Spring内部使用。

3.1.2 ApplicationContext体系

org.springframework.context.ApplicationContext是Spring上下文的底层接口,位于spring-context模块。它可以视作是Spring IOC容器的一种高级形式,也是我们用Spring企业开发时必然会用到的接口,它含有许多面向框架的特性,也对应用环境作了适配。

从上面的图中,我们可以看到ApplicationContext作为BeanFactory的子接口,与BeanFactory之间也是通过HierarchicalBeanFactory与ListableBeanFactory桥接的。
ApplicationContext接口,继承了MessageSource, ResourceLoader, ApplicationEventPublisher接口,以BeanFactory为主线添加了许多高级容器特性。

3.2 Spring创建Bean的大致过程

搞清楚整个Spring IOC容器创建Bean的过程,对于阅读源码的效率会有很大的提升。
下面梳理一下整个过程:

  1. 实例化BeanFactoryPostProcessor实现类
  2. 调用BeanFactoryPostProcessor#postProcessBeanFactory
  3. 实例化BeanPostProcessor实现类
  4. 调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
  5. 实例化Bean
  6. 调用InstantiationAwareBeanProcessor#postProcessAfterInstantiation
  7. 调用InstantiationAwareBeanPostProcessor#postProcessPropertyValues
  8. 为Bean注入属性
  9. 调用BeanNameAware#setBeanName
  10. 调用BeanClassLoaderAware#setBeanClassLoader
  11. 调用BeanFactoryAware#setBeanFactory
  12. 调用BeanPostProcessor#postProcessBeforeInitialization
  13. 调用InitializingBean#afterPropertiesSet
  14. 调用Bean的init-method
  15. 调用BeanPostProcessor#postProcessAfterInitialization

3.3 IOC容器依赖注入

完整来说,IOC容器的初始化过程中做了在容器中建立BeanDefinition的数据映射。之后所有的依赖的注入都依托于已经存在的BeanDefinition,限于篇幅,此处略去对BeanDefinition的建立作介绍。直接从上下文的getBean开始看起。

在AbstractApplicationContext抽象类中有一个getBeanFactory方法用于返回一个ConfigurableListableBeanFactory,所有BeanFactory接口的方法实际上都委托给子类内部的ConfigurableListableBeanFactory实现。

我们以AnnotationConfigApplicationContext,它在被构造时,内部的beanFactory实际上是由父类GenericApplicationContext来初始化一个DefaultListableBeanFactory的。

因此我们看某个bean是如何被加载的可以从DefaultListableBeanFactory的getBean方法看起,对于DefaultListableBeanFactory而言那些getBean方法实际上在AbstractBeanFactory这一层就都已经实现了,并且都委托给了AbstractBeanFactory#doGetBean。下面就来看一下doGetBean方法。

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;

    /*
     * 尝试从缓存中拿取一个bean实例。
     * Spring会在Bean还没完全初始化完毕的前,通过一个ObjectFactory提前暴露出bean实例,这样为解决循环依赖提供了遍历。
     */
    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 + "'");
            }
        }
        // 对FactoryBean的情况进行特殊处理。
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // 如果正在创建的bean为原型并且已经正在创建,这种循环依赖是无法解决的,要抛出异常。
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 如果该beanFactory中不包含要创建bean的beanDefinition,则尝试从父beanFactory中寻找。
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            String nameToLookup = originalBeanName(name);
            if (args != null) {
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

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

            // 有些bean是有depends-on/@DependsOn的,需要先初始化这些依赖。
            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);
                    getBean(dep);
                }
            }

            // 创建单例bean。
            if (mbd.isSingleton()) {
                /*
                 * 调用父类DefaultSingletonBeanRegistry的getSingleton,具体创建bean的工作实际上仍然是
                 * 回调参数中传递的ObjectFactory#getObject方法,而createBean实际上是子类AbstractAutowireCapableBeanFactory实现的。
                 */
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                // 对FactoryBean的情况进行特殊处理。
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            // 创建原型bean。
            else if (mbd.isPrototype()) {
                Object prototypeInstance = null;
                try {
                    // 前置处理,维护prototypesCurrentlyInCreation,加入当前bean记录。
                    beforePrototypeCreation(beanName);
                    // 委托给子类AbstractAutowireCapableBeanFactory来完成具体的创建bean工作。
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    // 后置处理,维护prototypesCurrentlyInCreation信息,删除当前bean记录。
                    afterPrototypeCreation(beanName);
                }
                // 对FactoryBean的情况进行特殊处理。
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                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 {
                                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就已经创建完了,最后一步检查类型,如果不匹配会尝试转换。
    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;
}

上面针对AbstractBeanFactory#doGetBean方法进行了源码分析,从中我们可以看出它主要会干这几件事情:

  1. 转换beanName。
  2. 尝试从缓存的单例中拿实例。
  3. 如果要创建的bean是原型模式,且已经在尝试创建,这种循环依赖是无法解决的。
  4. 当前beanFactory不包含要创建的bean的beanDefinition,会尝试从parentBeanFactory中获取。
  5. 如果当前bean有依赖(xml的话就是有depends-on,注解的话有@DependsOn),则需要先完成那些bean的创建初始化。
  6. 针对scope分类讨论创建。我们比较关心的就是单例,其次是原型。
  7. 类型检查,并且尝试转换。

我们一般比较关心的就是单例bean和原型bean的创建。
在获取单例bean时doGetBean方法会调用父类DefaultSingletonBeanRegistry#getSingleton。可以把DefaultSingletonBeanRegistry当作一个“单例bean桶”,因为它确实就是一个用来存放单例bean的桶。但是这个桶本身不关心bean到底该怎么创建,所以对于桶里还没有的bean,它将创建bean的职责通过回调ObjectFactory#getObject来完成,而AbstractBeanFactory中传递给getSingleton方法的ObjectFactory#getObject的具体实现是调用createBean,这个方法是真正创建并初始化bean的方法,由子类AbstractAutowireCapableBeanFactory完成。
对于获取原型bean则简单多了,不用关心放到桶里缓存的事情,直接调用createBean创建就是了。

所以我们接下来通过AbstractAutowireCapableBeanFactory来看一下一个Bean具体是如何创建并初始化的。

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

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

    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        /* 
         * 在对象被实例化前,这里有一个短路逻辑,会调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation。
         * 如果存在某个InstantiationAwareBeanPostProcessor的调用结果不为null,则形成了短路,接下来调用BeanPostProcessor#postProcessAfterInitialization。
         *
         * 实际上,一般Spring里默认就LazyInitTargetSourceCreator和QuickTargetSourceCreator可能会使得这里的短路生效。
         * 大部分情况AOP还是在bean被正常实例化后通过调用postProcessAfterInitialization实现的。
         */
        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);
    }

    // 创建bean的主要方法。
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
}

从上面可以看到AbstractAutowireCapableBeanFactory#createBean是创建bean的主要入口方法,但仍然不是最主要在“干活”的方法。继续向下看doCreateBean方法。

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

    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 尝试从factoryBean缓存中获取。
        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);

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

    /*
     * Spring为了解决单例bean的循环引用问题,会在bean还没有完全初始化完毕前通过添加singletonFactory
     * 使得其它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");
        }
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // 接下去初始化bean。
    Object exposedObject = bean;
    try {
        // 填充bean中的属性。
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            /*
             * 调用初始化方法,比如:
             * 1. 各种aware回调
             * 2. 调用BeanPostProcessor#postProcessBeforeInitialization
             * 3. 调用InitializingBean#afterPropertiesSet, xml中的init-method
             * 4. 调用BeanPostProcessor#postProcessAfterInitialization
             */
            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);
        /*
         * 上面的getSingleton第二个参数为false表示不会主动触发early reference的创建。
         * 所以此处earlySingletonReference只有在bean创建过程中发现有别的bean与当前bean有循环依赖才不为空。
         */
        if (earlySingletonReference != null) {
            /*
             * 如果当前bean调用initializeBean没有增强原始bean实例,则取earlySingletonReference。
             * 
             * 举例:
             * BeanA与BeanB互相依赖。Srping先创建BeanA,再创建BeanB。
             * BeanA通过addSingletonFactory暴露了获取BeanA引用的途径。
             *
             * 在populateBean的时候需要注入BeanB,而BeanB又需要注入BeanA,
             * 则在获取BeanA时会调用原先BeanA暴露的ObjectFactory,继而使得earlySingletonObjects中加入了BeanA引用。
             *
             * 回到BeanA的创建过程,走到此步时,发现initializeBean没有增强原始bean实例,
             * 则需要取其它循环依赖bean拿BeanA时在registry留下的结果(原始bean经过SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference回调)。
             */
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // 获取当前bean依赖的其它bean。
                String[] dependentBeans = getDependentBeans(beanName);
                // 过滤筛选出真正依赖的bean。
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                /*
                 * 举例:
                 * BeanA与BeanB互相依赖。Srping先创建BeanA,再创建BeanB。
                 * BeanA的创建走到这里时会抛出异常。
                 *
                 * 原因是上面的exposedObject != bean说明initializeBean方法的调用增强了原始的BeanA。
                 * 而BeanB中注入的BeanA很可能是原始beanA(可能会有SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference回调,
                 * 也就是BeanB中注入的BeanA不是此处BeanA的最终版exposedObject。
                 */
                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 {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

3.4 Bean的循环依赖是如何解决的

不是所有的循环依赖Spring都能够解决的。

  • 对于最简单的情况,bean为单例,且使用Autowired或者setter注入,Spring是可以解决这样的循环依赖的。通过上面的代码中我们可以看出,在一个Bean实例化后,会调用addSingletonFactory方法,在IOC容器中通过一个ObjectFactory暴露出可以获取还未完全初始化完毕的bean引用。若存在循环依赖,则依赖的bean可以在调用getBean时通过getSingleton方法获取到循环依赖的bean。

  • 但是Spring是不允许出现原型环的,举例来说,BeanA和BeanB循环依赖且scope都为prototype。因为prototype的bean,不会触发addSingletonFactory,即每次get这样的bean都会新创建一个。所以创建BeanA需要注入一个BeanB,而这个BeanB又需要注入一个新的BeanA,这样的循环依赖是没办法解决的。Spring会判断当前bean是否是prototype并且已经在创建中,然后抛出异常。

  • 对于构造器依赖,可以作一下讨论,下面讨论的bean的scope都为单例

    • 如果BeanA构造器中依赖BeanB,并且BeanA先创建,则无论BeanB以哪种形式依赖BeanA,都没办法解决这样的循环依赖。因为实例化BeanA需要先得到BeanB(此时还未提前暴露引用),BeanB依赖BeanA,但是拿不到BeanA提前暴露的引用,这就形成了无限循环。这种情况会在BeanB试图获取BeanA时在beforeSingletonCreation方法抛出异常。
    • 如果BeanA非构造器依赖BeanB,并且BeanA先创建,BeanB即使构造器依赖BeanA,也可以进行解决循环依赖。 因为这种情况BeanB可以拿到BeanA提前暴露的引用。

3.5 那些Aware究竟是什么

Spring中有很多XXXAware接口,从字面意思上很容易理解:就是bean能够“感知”XXX。通常这些接口的方法都是setXXX。在项目里做一个工具类实现ApplicationContextAware接口,里面可以塞一个ApplicationContext实例到静态域中,在代码中就可以很方便获取到Spring上下文进行一些操作。

那么Spring对于这些Aware接口是在哪一步调用的呢?答案其实在上面的源码分析中已经提到。在AbstractAutowireCapableBeanFactory#initializeBean方法中,Spring默认会对实现BeanNameAware, BeanClassLoaderAware, BeanFactoryAware进行回调,为它们注入beanName, classLoader, beanFactory等。

而对于更多的一些扩展,Spring基于那些processor实现了很强的可拓展性与可插拔性。比如我们非常熟悉的ApplicationContextAware接口实际上是通过ApplicationContextAwareProcessor来实际调用的,它继承了BeanPostProcessor,其中postProcessBeforeInitialization方法中会对EnvironmentAware, EmbeddedValueResolverAware, ApplicationContextAware等等一系列Aware接口的子类Bean进行回调,为其注入相关资源。

那么ApplicationContextAwareProcessor是什么时候出现在BeanPostProcessor集合中的呢?在AbstractApplicationContext#prepareBeanFactory方法中,Spring有如下代码:

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

也就是当Spring上下文在初始化prepareBeanFactory的时候就已经添加了ApplicationContextAwareProcessor。

posted @ 2017-09-16 00:04  活在夢裡  阅读(6217)  评论(0编辑  收藏  举报