Spring 容器创建Bean的过程

70 阅读9分钟

首先区分下实例化和初始化的语义

  • 实例化是创建一个对象的过程,
  • 初始化则是在创建对象时给对象赋予初始值的过程

1. Bean 的创建过程

对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactory 的 createBean(...)方法进行创建,

创建 Bean 的过程涉及到 Bean 生命周期的大部分阶段,例如实例化阶段、属性赋值阶段、Aware 接口回调阶段、初始化阶段都是在这个方法中完成的。

1.1. AbstractAutowireCapableBeanFactory

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory 抽象类,继承 AbstractBeanFactory,实现 AutowireCapableBeanFactory 接口,完成 Bean 的创建

1.1.1. createBean 方法

createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 方法,创建 Bean,方法如下:

@Override
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;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    // <1> 获取 `mbd` 对应的 Class 对象,确保当前 Bean 能够被创建出来
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    // 如果这里获取到了 Class 对象,但是 `mbd` 中没有 Class 对象的相关信息,表示这个 Class 对象是动态解析出来的
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        // 复制一份 `mbd`,并设置 Class 对象,因为动态解析出来的 Class 对象不被共享
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides.
    try {
        // <2> 对所有的 MethodOverride 进行验证和准备工作(确保存在对应的方法,并设置为不能重复加载)
        mbdToUse.prepareMethodOverrides();
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        /**
         * <3> 在实例化前进行相关处理,会先调用所有 {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation}
         * 注意,如果这里返回对象不是 `null` 的话,不会继续往下执行原本初始化操作,直接返回,也就是说这个方法返回的是最终实例对象
         * 可以通过这种方式提前返回一个代理对象,例如 AOP 的实现,或者 RPC 远程调用的实现(因为本地类没有远程能力,可以通过这种方式进行拦截)
         */
        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 {
        // <4> 创建 Bean 对象 `beanInstance`,如果上一步没有返回代理对象,就只能走常规的路线进行 Bean 的创建了
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        // <5> 将 `beanInstance` 返回
        return beanInstance;
    } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

入参:

  • beanName:Bean 的名称
  • mbd:Bean 的 BeanDefinition 对象(合并后)
  • args:创建 Bean 的参数,我们通常不会传,所以这里为 null

过程大致如下:

  1. 获取 mbd 对应的 Class 对象,确保当前 Bean 能够被创建出来,调用 resolveBeanClass(...) 方法
  2. 对所有的 MethodOverride 进行验证和准备工作(确保存在对应的方法,并设置为不能重复加载)
  3. 实例化前阶段在实例化前进行相关处理,会先调用所有 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation注意,如果这里返回对象不是 null 的话,不会继续往下执行原本初始化操作,直接返回,也就是说这个方法返回的是最终实例对象可以通过这种方式提前返回一个代理对象,例如 AOP 的实现,或者 RPC 远程调用的实现(因为本地类没有远程能力,可以通过这种方式进行拦截)
  4. 创建 Bean 对象 beanInstance,如果上一步没有返回代理对象,就只能走常规的路线进行 Bean 的创建了,调用 doCreateBean(...) 方法
  5. 将 beanInstance 返回

可以看到这个方法中并没有开始真正 Bean 的创建,在这个方法的第 4 步会调用 doCreateBean(...) 方法创建 Bean

1.1.2. doCreateBean 方法

doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) ,创建 Bean,方法如下:

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

    // Instantiate the bean.
    /**
     * <1> Bean 的实例化阶段,会将 Bean 的实例对象封装成 {@link BeanWrapperImpl} 包装对象
     * BeanWrapperImpl 承担的角色:
     * 1. Bean 实例的包装
     * 2. {@link org.springframework.beans.PropertyAccessor} 属性编辑器
     * 3. {@link org.springframework.beans.PropertyEditorRegistry} 属性编辑器注册表
     * 4. {@link org.springframework.core.convert.ConversionService} 类型转换器(Spring 3+,替换了之前的 TypeConverter)
     */
    BeanWrapper instanceWrapper = null;
    // <1.1> 如果是单例模式,则先尝试从 `factoryBeanInstanceCache` 缓存中获取实例对象,并从缓存中移除
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // <1.2> 使用合适的实例化策略来创建 Bean 的实例:工厂方法、构造函数自动注入、简单初始化
    // 主要是将 BeanDefinition 转换为 BeanWrapper 对象
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // <1.3> 获取包装的实例对象 `bean`
    final Object bean = instanceWrapper.getWrappedInstance();
    // <1.4> 获取包装的实例对象的类型 `beanType`
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    // <2> 对 RootBeanDefinition(合并后)进行加工处理
    synchronized (mbd.postProcessingLock) { // 加锁,线程安全
        // <2.1> 如果该 RootBeanDefinition 没有处理过,则进行下面的处理
        if (!mbd.postProcessed) {
            try {
                /**
                 * <2.2> 对 RootBeanDefinition(合并后)进行加工处理
                 * 调用所有 {@link MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition}
                 * 例如有下面两个处理器:
                 * 1. AutowiredAnnotationBeanPostProcessor 会先解析出 @Autowired@Value 注解标注的属性的注入元信息,后续进行依赖注入;
                 * 2. CommonAnnotationBeanPostProcessor 会先解析出 @Resource 注解标注的属性的注入元信息,后续进行依赖注入,
                 * 它也会找到 @PostConstruct@PreDestroy 注解标注的方法,并构建一个 LifecycleMetadata 对象,用于后续生命周期中的初始化和销毁
                 */
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            // <2.3> 设置该 RootBeanDefinition 被处理过,避免重复处理
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // <3> 提前暴露这个 `bean`,如果可以的话,目的是解决单例模式 Bean 的循环依赖注入
    // <3.1> 判断是否可以提前暴露
    boolean earlySingletonExposure = (mbd.isSingleton() // 单例模式
            && this.allowCircularReferences // 允许循环依赖,默认为 true
            && isSingletonCurrentlyInCreation(beanName)); // 当前单例 bean 正在被创建,在前面已经标记过
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        /**
         * <3.2>
         * 创建一个 ObjectFactory 实现类,用于返回当前正在被创建的 `bean`,提前暴露,保存在 `singletonFactories` (**三级 Map**)缓存中
         *
         * 可以回到前面的 {@link AbstractBeanFactory#doGetBean#getSingleton(String)} 方法
         * 加载 Bean 的过程会先从缓存中获取单例 Bean,可以避免单例模式 Bean 循环依赖注入的问题
         */
        addSingletonFactory(beanName,
                // ObjectFactory 实现类
                () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    // 开始初始化 `bean`
    Object exposedObject = bean;
    try {
        // <4> 对 `bean` 进行属性填充,注入对应的属性值
        populateBean(beanName, mbd, instanceWrapper);
        // <5> 初始化这个 `exposedObject`,调用其初始化方法
        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);
        }
    }

    // <6> 循环依赖注入的检查
    if (earlySingletonExposure) {
        // <6.1> 获取当前正在创建的 `beanName` 被依赖注入的早期引用
        // 注意,这里有一个入参是 `false`,不会调用上面第 `3` 步的 ObjectFactory 实现类
        // 也就是说当前 `bean` 如果出现循环依赖注入,这里才能获取到提前暴露的引用
        Object earlySingletonReference = getSingleton(beanName, false);
        // <6.2> 如果出现了循环依赖注入,则进行接下来的检查工作
        if (earlySingletonReference != null) {
            // <6.2.1> 如果 `exposedObject` 没有在初始化阶段中被改变,也就是没有被增强。则使用提前暴露的那个引用
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            // <6.2.2> 否则,`exposedObject` 已经不是被别的 Bean 依赖注入的那个 Bean
            else if (!this.allowRawInjectionDespiteWrapping // 是否允许注入未加工的 Bean,默认为 false,这里取非就为 true
                    && hasDependentBean(beanName)) { // 存在依赖 `beanName` 的 Bean(通过 `depends-on` 配置)
                // 获取依赖当前 `beanName` 的 Bean 们的名称(通过 `depends-on` 配置)
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                // 接下来进行判断,如果依赖 `beanName` 的 Bean 已经创建
                // 说明当前 `beanName` 被注入了,而这里最终的 `bean` 被包装过,不是之前被注入的,则抛出异常
                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.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        /**
         * <7> 为当前 `bean` 注册 DisposableBeanAdapter(如果需要的话),用于 Bean 生命周期中的销毁阶段
         * 可以看到 {@link DefaultSingletonBeanRegistry#destroySingletons()} 方法
         */
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    // <8> 返回创建好的 `exposedObject` 对象
    return exposedObject;
}

这个方法的处理过程有点长,如下:

  1. Bean 的实例化阶段,会将 Bean 的实例对象封装成 BeanWrapperImpl 包装对象

    1. 如果是单例模式,则先尝试从 factoryBeanInstanceCache 缓存中获取实例对象,并从缓存中移除
    2. 使用合适的实例化策略来创建 Bean 的实例:工厂方法、构造函数自动注入、简单初始化,主要是将 BeanDefinition 转换为 BeanWrapper 对象调用 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 方法
    3. 获取包装的实例对象 bean
    4. 获取包装的实例对象的类型 beanType
  2. 对 RootBeanDefinition(合并后)进行加工处理

    1. 如果该 RootBeanDefinition 没有处理过,则进行下面的处理
    2. 调用所有的 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition,这个过程非常重要,例如 Spring 内有下面两个处理器:
      1. AutowiredAnnotationBeanPostProcessor,会先解析出 @Autowired@Value 注解标注的属性的注入元信息,后续进行依赖注入
      2. CommonAnnotationBeanPostProcessor,会先解析出 @Resource 注解标注的属性的注入元信息,后续进行依赖注入,它也会找到 @PostConstruct@PreDestroy 注解标注的方法,并构建一个 LifecycleMetadata 对象,用于后续生命周期中的初始化和销毁
    3. 设置该 RootBeanDefinition 被处理过,避免重复处理
  1. 提前暴露这个 bean,如果可以的话,目的是解决单例模式 Bean 的循环依赖注入
    1. 判断是否可以提前暴露,满足三个条件:单例模式、允许循环依赖(默认为 true)、当前单例 bean 正在被创建,在前面已经标记过
    2. 创建一个 ObjectFactory 实现类,用于返回当前正在被创建的 bean,提前暴露,保存在 singletonFactories三级 Map)缓存中

接下来开始初始化上面的 bean 实例对象,会先创建一个 Object exposedObject 等于 bean (引用)

  1. bean 进行属性填充,注入对应的属性值,调用 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) 方法

  2. 初始化这个 exposedObject,调用其初始化方法,调用 initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) 方法

  3. 循环依赖注入的检查

    1. 获取当前正在创建的 beanName 被依赖注入的早期引用,调用 DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference) 方法。注意,这里有一个入参是 false,不会调用上面第 3 步的 ObjectFactory 实现类,也就是说当前 bean 如果出现循环依赖注入,这里才能获取到提前暴露的引用
    2. 如果出现了循环依赖注入,则进行接下来的检查工作
      1. 如果 exposedObject 没有在初始化阶段中被改变,也就是没有被增强,则使用提前暴露的那个引用
      2. 否则 exposedObject 已经不是被别的 Bean 依赖注入的那个 Bean,如果依赖当前 beanName 的 Bean(通过 depends-on 配置)已经被创建,则抛出异常
  4. 为当前 bean 注册 DisposableBeanAdapter(如果需要的话),用于 Bean 生命周期中的销毁阶段

  5. 返回创建好的 exposedObject 对象