摘要

了解spring bean的创建初始化过程可以让我们更加方便的进行spring bean的扩展编程。本文主要是讨论spring bean创建的主要过程,一些方法细节没有深入的讨论。文章使用的spring 版本为:5.3.15.

BeanDefinition Merged

获取bean时,会调用到AbstractBeanFactory#doGetBean 方法,doGetBean调用getMergedLocalBeanDefinition。getMergedLocalBeanDefinition的作用是返回一个合并过的RootBeanDefinition,如果指定的 bean 对应于子 bean 定义,则遍历父 bean 定义。在XML定义的bean在spring解析时bean的定义通常先表示为GenericBeanDefinition,通过注解定义的bean ,bean的定义通常表示为AnnotatedBeanDefinition,通过getMergedLocalBeanDefinition 统一将bean的定义转换为RootBeanDefinition。

实例化

实例化前置操作

AbstractBeanFactory#createBean中会调用AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation,resolveBeforeInstantiation的源码如下。

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


protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
      Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
      if (result != null) {
         return result;
      }
   }
   return null;
}

InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 是spring bean 创建过程中的一个扩展点。从上面的源码可以看出,如果这个方法返回一个非空对象,bean的创建过程就会被短路(后续的创建过程被中断, 后续的唯一的处理是来自配置BeanPostProcessors 的 postProcessAfterInitialization 回调)。如果resolveBeforeInstantiation返回非空对象,那么这个非空对象就是创建的bean对象(参考下面的createBean的代码片段)。

    try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            //如果bean不为空,函数返回这个bean对象,可以通过InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 拦截bean的正常创建
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

实例化

如果前置操作返回空对象,那么进入正常实例化bean阶段(AbstractAutowireCapableBeanFactory#doCreateBean)。

实例化bean(createBeanInstance )

createBeanInstance方法里,会通过RootBeanDefinition中配置的信息,创建出bean实例化对象(比如通过:构造器、配置的工厂方法等),返回包裹bean对象的BeanWrapper对象。BeanWrapper是Spring 底层 JavaBeans 基础设施的核心接口。提供了分析和操作标准JavaBean的操作,包括:get和set属性值的能力、get属性描述符并且查询属性的可读/可写性。

applyMergedBeanDefinitionPostProcessors

doCreateBean完成createBeanInstance后,调用applyMergedBeanDefinitionPostProcessors。applyMergedBeanDefinitionPostProcessors的代码如下,调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法。根据spring文档介绍,此时bean还没有进行populateBean操作,postProcessMergedBeanDefinition可以内省bean的定义来以便在对 bean 的实际实例进行后处理之前准备一些缓存的元数据

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
            processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }

populateBean

接下来就进入到populateBean阶段。在这个阶段首先调用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation,这是实例化后置处理器。这是在 Spring 的自动装配开始之前对给定 bean 实例执行自定义字段注入的理想回调处。

继续往下会调用InstantiationAwareBeanPostProcessor#postProcessProperties。InstantiationAwareBeanPostProcessor 中有两个的方法:postProcessProperties postProcessPropertyValues,他们的作用都是在bean的属性处理前,可以对properties就行相关操作。postProcessProperties 从spring 5.1引入,5.1同时postProcessPropertyValues 置为Deprecated。

postProcessProperties 在工厂将给定的属性值应用于给定的 bean 之前对给定的属性值进行后处理。默认返回null。如果提供了自定义的postProcessPropertyValues实现,那么该方法应该返回null,否则应该返回响应的PropertyValues。下面的代码是populateBean中 postProcessProperties处理的相关代码。

PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
                PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
//如果InstantiationAwareBeanPostProcessor#postProcessProperties返回为null,会进行InstantiationAwareBeanPostProcessor#postProcessPropertyValues 调用
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }

        if (pvs != null) {
            applyPropertyValues(beanName, mbd, bw, pvs);
        }

从上面代码看,在处理完postProcessProperties后,调用applyPropertyValues。将处理好的PropertyValues解析到bean。这个方法做的事情包括引用解析、类型转换、依赖处理等。

初始化(init)

完成了bean的实例化,并且完成populateBean之后,代码进入到AbstractAutowireCapableBeanFactory#initializeBean进行bean的初始化工作。

Aware回调

initializeBean首选调用invokeAwareMethods检测bean是否实现了Aware相关接口,依次进行检测并回调:
BeanNameAware. setBeanName
BeanClassLoaderAware. setBeanClassLoader
BeanFactoryAware.setBeanFactory

init前置处理器(BeanPostProcessor#postProcessBeforeInitialization)

initializeBean调用applyBeanPostProcessorsBeforeInitialization,依次调用配置好的init前置处理器。
参考下spring文档:postProcessBeforeInitialization在任何 bean 初始化回调(如 InitializingBean 的 afterPropertiesSet 或自定义初始化方法)之前,将此 BeanPostProcessor 应用于给定的新 bean 实例。 该 bean 将已经填充了属性值。 返回的 bean 实例可能是原始实例的包装器。

初始化方法

init前置处理完成后,进行初始化方法的调用(invokeInitMethods)。invokeInitMethods首先检查bean是否实现了InitializingBean,如果实现了这个接口,则调用InitializingBean#afterPropertiesSet。 然后检查bean的定义是否配置了初始化方法,如果配置了初始化方法进行调用。

init后置处理器(BeanPostProcessor#postProcessAfterInitialization)

initializeBean最后调用applyBeanPostProcessorsAfterInitialization,依次调用配置好的init后置处理器。
spring 说明:在任何 bean 初始化回调(如 InitializingBean 的 afterPropertiesSet 或自定义初始化方法)之后,将此 BeanPostProcessor 应用于给定的新 bean 实例。 该 bean 将已经填充了属性值。 返回的 bean 实例可能是原始实例的包装器。

在 FactoryBean 的情况下,将为 FactoryBean 实例和由 FactoryBean 创建的对象(从 Spring 2.0 开始)调用此回调。 后处理器可以通过相应的 bean instanceof FactoryBean 检查来决定是否应用于 FactoryBean 或创建的对象或两者。


tiger1000
2 声望3 粉丝

每天进步一点点,轻松又又快乐