Spring refresh 方法详解

对应上一章的流程梳理,这里定位到源码中看看 Spring 中 bean 创建的具体流程

本来是想梳理 refresh 的整个流程,但是发现太长了,于是只好缩小目标,这一章的目标是 把 SpringBean 创建 这一步的流程给梳理明白了。

但是整个线索还是 AbstractApplicationContext 中的 refresh 方法,这个方法作为贯穿整个过程的线索。

流程图:

这里仍然可以参考 Spring IoC 工作流程梳理 这一章的内容,具体来说图还是这张,只是我们的关注点在于 BeanFactory 自己的初始化,以及初始化之后怎样创建 XML 中我们定义的 Bean 实例。

也就是我们本章的内容只到红框中的部分为止:

image-20201117174606157

Spring Bean 创建具体执行流程源码追踪与梳理:

refresh 流程图 从初始化 BeanFactory 到 Bean 实例创建结束

起点:

org.springframework.context.support.AbstractApplicationContext

refresh() 方法 是 Spring 容器的核心方法,这里是入口,也是容器真正初始化的地方。

由于 refresh 的重要性,所以这里我搬运了完整的代码,并添加了一些注释,后续的代码可能我会只截取最重要的部分,因为如果完整搬运的话,太长了,并且无法突出重点。

@Override
public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
    // Prepare this context for refreshing.
    // 准备上下文环境
    prepareRefresh(); // ①

    // Tell the subclass to refresh the internal bean factory.
    // 创建并初始化 BeanFactory
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // ②

    // Prepare the bean factory for use in this context.
    // 填充 BeanFactory 功能,使其可用
    prepareBeanFactory(beanFactory); // ③

    try {
      // Allows post-processing of the bean factory in context subclasses.
      // 提供子类覆盖的额外处理,即子类自己的扩展点BeanFactoryPostProcessor
      postProcessBeanFactory(beanFactory); // ④

      // Invoke factory processors registered as beans in the context.
      // 激活BeanFactory处理器
      invokeBeanFactoryPostProcessors(beanFactory); // ⑤

      // Register bean processors that intercept bean creation.
      // 注册拦截Bean创建的处理器,注册 BeanPostProcessor 
      registerBeanPostProcessors(beanFactory); // ⑥

      // i18n 国际化相关处理
      initMessageSource(); // ⑦

      // 广播器的注册
      initApplicationEventMulticaster(); // ⑧

      // 另一个模板方法的应用,空实现,交给子类自己处理
      onRefresh(); // ⑨

      // 绑定监听器,为后续的监听事件回调做准备
      registerListeners(); // ⑩

      // Instantiate all remaining (non-lazy-init) singletons.
      // 真正对 Bean 进行实例化的地方,初始化所有非懒加载的单例对象
      finishBeanFactoryInitialization(beanFactory); // 11

      // Last step: publish corresponding event.
      finishRefresh(); // 12
    }

    catch (BeansException ex) {
      if (logger.isWarnEnabled()) {
        logger.warn("Exception encountered during context initialization - " +
                    "cancelling refresh attempt: " + ex);
      }

      // Destroy already created singletons to avoid dangling resources.
      destroyBeans();

      // Reset 'active' flag.
      cancelRefresh(ex);

      // Propagate exception to caller.
      throw ex;
    }

    finally {
      // Reset common introspection caches in Spring's core, since we
      // might not ever need metadata for singleton beans anymore...
      resetCommonCaches();
    }
  }
}

1、创建 BeanFactory 对象 —— refresh()#prepareRefresh();

// org.springframework.context.support.AbstractApplicationContext
// 完成准备工作,包括设置启动日期( startup date)
//活动标志(active flag)
//属性源的初始化工作( initialization of property sources.)
protected void prepareRefresh() {
  // 设置启动时间,flag 初始化值
  this.startupDate = System.currentTimeMillis();
  this.closed.set(false);
  this.active.set(true);

  if (logger.isDebugEnabled()) {
    if (logger.isTraceEnabled()) {
      logger.trace("Refreshing " + this);
    }
    else {
      logger.debug("Refreshing " + getDisplayName());
    }
  }

  // Initialize any placeholder property sources in the context environment.
  // 初始化某些资源
  initPropertySources();

  // 验证属性值
  getEnvironment().validateRequiredProperties();

  // Store pre-refresh ApplicationListeners...
  // 下面创建了一系列的 Set 集合(暂时忽略)
  if (this.earlyApplicationListeners == null) {
    this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
  }
  else {
    // Reset local application listeners to pre-refresh state.
    this.applicationListeners.clear();
    this.applicationListeners.addAll(this.earlyApplicationListeners);
  }

  // Allow for the collection of early ApplicationEvents,
  // to be published once the multicaster is available...
  this.earlyApplicationEvents = new LinkedHashSet<>();
}

2、obtainFreshBeanFactory —— 获取最新的 BeanFactory ,因为之前程序中可能已经存在 BeanFactory

// org.springframework.context.support.AbstractApplicationContext
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  refreshBeanFactory();
  return getBeanFactory();
}

// 跳转到 refreshBeanFactory 方法中,其具体实现类是 AbstractRefreshableApplicationContext

// org.springframework.context.support.AbstractRefreshableApplicationContext
@Override
protected final void refreshBeanFactory() throws BeansException {
  // 如果已经存在 BeanFactory,则进行销毁
  if (hasBeanFactory()) {
    destroyBeans();
    closeBeanFactory();
  }
  try {
    // 开始创建 BeanFactory 
    DefaultListableBeanFactory beanFactory = createBeanFactory();
    beanFactory.setSerializationId(getId());
    customizeBeanFactory(beanFactory);
    // 读取 BeanDefinition 信息
    loadBeanDefinitions(beanFactory);
    synchronized (this.beanFactoryMonitor) {
      this.beanFactory = beanFactory;
    }
  }
  catch (IOException ex) {
    throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
  }
}

// org.springframework.context.support.AbstractRefreshableApplicationContext
// 创建默认的对象工厂 DefaultListableBeanFactory
protected DefaultListableBeanFactory createBeanFactory() {
  return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}


读取 BeanDefinition

org.springframework.context.support.AbstractXmlApplicationContext 类中的 loadBeanDefinitions 方法,读取了 XML 中定义的 Bean 信息

可以看到在 AbstractRefreshableApplicationContext 中并没有实现 loadBeanDefinitions 方法,因为对应了不同的情况,这里我的 Bean 是定义在 XML 中的,所以我选择查看 AbstractXmlApplicationContext 中的实现

image-20201117141702437

image-20201117141634198

这一步执行完成之后, beanDefinitionMap 就有值了:

image-20201117141859760

对应了我在 XML 中定义的 Bean

image-20201117141926443

loadBeanDefinitions 执行完,这一步就完成了,返回了 refresh() 的主流程。

3、 prepareBeanFactory —— 初始化 BeanFactory ,进行必须的赋值操作:

上一步 obtainFreshBeanFactory 完成之后 BeanFactory 已经创建好了,但是很多值还没有初始化,也就是还不是真正可用的状态,refresh 中下一步就是 prepareBeanFactory 对其进行初始化:

尚未初始化的 BeanFactory:可以看到有很多的 0null ,这些都是默认值。

image-20201117142212769

初始化完成后:

image-20201117142419410

这一步并不复杂,只需要知道是初始化就行了,细节暂时不用深究。

4、postProcessBeanFactory —— 模板方法设计模式 ,预留的扩展点

// 模板方法,留给开发者需要做扩展的时候自己实现
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

可以看到,这里点进去之后并没有实现,这里就是一个模板,就是 BeanFactoryPostProcessor ,是 Spring 预留的扩展点。

Springboot 中就在对这个方法做出了扩展,如果需要进行扩展则由开发者自己进行实现。

5、 invokeBeanFactoryPostProcessors —— BeanFactoryPostProcessor 进行增强

对应源码位置:

org.springframework.context.support.AbstractApplicationContextinvokeBeanFactoryPostProcessors 方法

BeanFactoryPostProcessor 的功能对应流程图中的红框部分:

  • 替换属性
  • 修改 BeanDefinition
  • ... 其他功能等

image-20201117150935694

6、 registerBeanPostProcessors —— 绑定 BeanPostProcessor 处理器

这里的 BeanPostProcessor 和上一步的 BeanFactoryPostProcessor 并不是一个东西,希望大家不要混淆了,如图所示:

image-20201117151358512

//org.springframework.context.support.AbstractApplicationContext
// 实例化并绑定 BeanPostProcessor ,并没有真正执行 BeanPostProcessor 中的代码
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

7、国际化处理 i 18n —— initMessageSource

非重要内容,暂时略过。

8、initApplicationEventMulticaster (重点) 初始化事件广播

用来发布处理后续发布的事件,与 Bean 的创建也无太大关系,略过。

9、onRefresh —— 又一个模板方法的扩展点

//org.springframework.context.support.AbstractApplicationContext
// 又是一个模板方法的扩展点,暂时略过
protected void onRefresh() throws BeansException {
  // For subclasses: do nothing by default.
}

10、registerListeners 注册监听器

为了满足在 bean 创建过程中对事件的回调,先要将监听器和广播准备好。

image-20201117152200804

11、 finishBeanFactoryInitialization —— 开始进行实例化工作(重点)

Instantiate all remaining (non-lazy-init) singletons.实例化所有非懒加载的单例对象

//org.springframework.context.support.AbstractApplicationContext
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  // 属性值的初始化 代码省略
  ...
  // Instantiate all remaining (non-lazy-init) singletons.
  // 关键在最后一句,开始初始化非懒加载的单例对象
  beanFactory.preInstantiateSingletons();
}

点进 preInstantiateSingletons 方法,发现跳到了一个接口 : ConfigurableListableBeanFactory,找到具体的实现: org.springframework.beans.factory.support.DefaultListableBeanFactory

这里可以看到 beanNames 这个 List 中保存的就是我们在 XML 中定义的 bean 的名称。

这里由于代码中嵌套的层级很深,所以我们仍然需要抓住重点

  • 找到 Spring具体创建对象的地方,也就是具体使用 反射 的地方。
// org.springframework.beans.factory.support.DefaultListableBeanFactory
@Override
public void preInstantiateSingletons() throws BeansException {
  // 加载完 XML 文件之后,所有定义的 Bean 都在这个列表中
  List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  
  // 循环实例化 beanNames 中对应的 bean 对象
  for (String beanName : beanNames) {
    // 获取 bean 描述信息
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    // 判断 bean 是否抽象、是否单例、是否懒加载
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
      // 判断是否是 FactoryBean
      // 代码忽略
      else {
        // 关键代码:获取 bean,跳入这个方法中
        getBean(beanName);
      }
    }
  }
  // 还有一段循环,关系不大,所以忽略了。
}

跳入 getBean 方法中,创建 bean 的具体逻辑在这个方法里面:

// org.springframework.beans.factory.support.AbstractBeanFactory
@Override
public Object getBean(String name) throws BeansException {
  return doGetBean(name, null, null, false);
}

这里重点又来了,源码中 do 开头的方法一般是真正的底层具体逻辑,所以进入 doGetBean

这个方法很长,直接来看关键代码:createBean

// org.springframework.beans.factory.support.AbstractBeanFactory
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                          @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  final String beanName = transformedBeanName(name);
  Object bean;
  // Eagerly check singleton cache for manually registered singletons
  // 判断是否是单例对象,第一次创建时对象不存在,所以 sharedInstance 为 null
  Object sharedInstance = getSingleton(beanName);
  // 如果是第一次创建的话, sharedInstance 为 null,所以下面的判断进不去
  if (sharedInstance != null && args == null) {
  	// 代码省略...
  }
    try {
      // 获取bean中的依赖信息
      String[] dependsOn = mbd.getDependsOn();
      // Create bean instance.
      if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
          try {
            // 关键代码,真正创建 bean 的地方,点进去。
            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);
      }
      //... 还有一大段逻辑,与本次无关,直接忽略
}

点进 createBean 看具体实现:

// org.springframework.beans.factory.support.AbstractBeanFactory
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  throws BeanCreationException;

这里第一次跳进去是 AbstractBeanFactory 中的空实现,下一步就是找到其具体的实现类:

AbstractAutowireCapableBeanFactory 类中,实现了 createBean 的具体逻辑。

这个方法也很长,我们需要找到其核心的方法: do 开头的 doCreateBean

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
@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.
  Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
  if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    mbdToUse = new RootBeanDefinition(mbd);
    mbdToUse.setBeanClass(resolvedClass);
  }

  // Prepare method overrides.
  try {
    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.
    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 {
    // 核心方法,主要看这里面的逻辑
    if (logger.isTraceEnabled()) {
      logger.trace("Finished creating instance of bean '" + beanName + "'");
    }
    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);
  }
}

下面看 doCreateBean 的具体代码:

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
// 这里只关注2个方法即可:createBeanInstance ——> 创建 bean , populateBean --> 填充bean
// 这里同样删除了大量代码,只找最主要的地方
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  throws BeanCreationException {

  // Instantiate the bean.
  // 创建一个 Bean 的包装类
  BeanWrapper instanceWrapper = null;
  if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  }
  if (instanceWrapper == null) {
    // 重点: 具体的实例化地方,跳入 createBeanInstance 方法中看细节
    instanceWrapper = createBeanInstance(beanName, mbd, args);
  }
  final Object bean = instanceWrapper.getWrappedInstance();
  Class<?> beanType = instanceWrapper.getWrappedClass();
  if (beanType != NullBean.class) {
    mbd.resolvedTargetType = beanType;
  }
  
  Object exposedObject = bean;
  // 填充 bean 属性
  populateBean(beanName, mbd, instanceWrapper);
  return exposedObject;
}

createBeanInstance :仍然不是最底层创建 bean 的地方,继续寻找。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
  // Candidate constructors for autowiring?
  // 关键点来了,这个方法的返回值是构造器
  Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  // No special handling: simply use no-arg constructor.
  // 继续跳入这个方法
  return instantiateBean(beanName, mbd);
}
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
  try {
    Object beanInstance;
    final BeanFactory parent = this;
    if (System.getSecurityManager() != null) {
      beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                                                   getInstantiationStrategy().instantiate(mbd, beanName, parent),
                                                   getAccessControlContext());
    }
    else {
      // 获取实例化策略
      // 跳入 instantiate 中看细节
      beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    }
    BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    initBeanWrapper(bw);
    return bw;
  }
  catch (Throwable ex) {
    throw new BeanCreationException(
      mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  }
}

instantiate 已经接近 Spring 最底层使用 反射构造对象的地方了

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // 跳入这里的具体逻辑中
    return BeanUtils.instantiateClass(constructorToUse);
}

instantiateClass —— 真正干活的地方

// org.springframework.beans.BeanUtils
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
  // 真正使用反射创建对象的地方,就是这一行!
  return ctor.newInstance(argsWithDefaultValues);
}

到这里 bean 的创建才算真正完成了: 我们寻寻觅觅,终于找到了真正干活的地方

image-20201117160145042

下一步:填充 bean 属性(放到下一章去学习)

参考资料

马士兵 spring(p1 ~ p7 是我所梳理和添加的一些内容)

照着这个视频进行的梳理,自己修改了一下顺序,看起来更加自然。 最大的收获就是视频中老师所说的,看源码要有重点,奔着自己的目标,只梳理最主要的流程,不要每个方法都试图弄明白,那样很快会迷失在源码中。

我这次的目标就是梳理 Bean 创建的流程,我实现了,找到了 Spring 中具体创建 Bean 的地方。

希望你也有收获。

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

最是人间留不住,曾是惊鸿照影来。