Spring5源码11-容器刷新refresh方法(注解版)

首先需要明确,这里调用的 refresh() 方法是 AnnotationConfigApplicationContext 上下文, obtainFreshBeanFactory() 获取的 beanFactory 实际类型是 DefaultListableBeanFactory 。

首先我们来看整体代码, refresh() 的方法很清晰,因为他将所有的功能封装到了各个方法中。后面我们会来一一介绍这些方法。

// 容器刷新的十二大步骤
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 容器启动的状态
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

      // Prepare this context for refreshing.
      // 1.准备上下文环境,作用就是初始化一些状态和属性,为后面的工作做准备。
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      /** 2. 工厂创建:BeanFactory 第一次开始创建的时候,有xml解析逻辑
       *      2.1、创建BeanFactory对象
       *     2.2、xml解析
       *           传统标签解析:bean、import等
       *           自定义标签解析 如:<context:component-scan base-package="org.example"/>
       *           自定义标签解析流程:
       *              a、根据当前解析标签的头信息找到对应的namespaceUri
       *              b、加载spring所以jar中的spring.handlers文件。并建立映射关系
       *              c、根据namespaceUri从映射关系中找到对应的实现了NamespaceHandler接口的类
       *              d、调用类的init方法,init方法是注册了各种自定义标签的解析类
       *              e、根据namespaceUri找到对应的解析类,然后调用paser方法完成标签解析
       *        2.3、把解析出来的xml标签封装成BeanDefinition对象
       */
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      // 3. 预准备工厂,给容器中注册了环境信息作为单实例Bean  方便后续自动装配
      // 并且放了一些后置处理器(监听、xxxAware功能)
      prepareBeanFactory(beanFactory);

      try {
         //  Allows post-processing of the bean factory in context subclasses.
         // 4. 留给子类的模板方法,允许子类继续对工厂执行一些处理
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // Invoke factory processors registered as beans in the context.
         // 5. 【大核心】工厂增强:执行所有的BeanFactory 后置增强器 利用BeanFactory后置增强器对工厂进行修改或增强
         // 配置类ConfigurationClassPostProcessor也会在这个解析
         // BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor 完成对这两个接口的调用
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         // 6. 【核心】注册 所有的Bean的后置处理器
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();

         // Initialize message source for this context.
         // 7. 初始化国际化组件
         initMessageSource();

         // Initialize event multicaster for this context.
         // 8. 初始化事件派发 功能
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 9. 留给子类继续增强处理逻辑
         // 这个方法着重理解模板设计模式,因为在springboot中,这个方法是用来做内嵌tomcat启动的
         onRefresh();

         // Check for listener beans and register them.
         // 10. 注册事件监听器,从容器中获取所有的ApplicationListener
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         /**
          * 11. 【大核心】bean创建:完成BeanFactory 初始化(工厂里面所有的组件都好了)
          *        这个方法一定要理解要具体看
          *        11.1、bean实例化过程
          *        11.2、ioc
          *        11.3、注解支持
          *        11.4、BeanPostProcessor的执行
          *        11.5、Aop的入口
          */
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         // 12. 发布事件
         finishRefresh();
      }
      ...
      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
         contextRefresh.end();
      }
   }
}
复制代码

下面简单概括一下上面的初始化步骤:

  1. prepareRefresh : 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。在某些情况下项目的使用需要读取某些系统变量,那么在启动时候,就可以通过准备函数来进行参数的校验。
  2. obtainFreshBeanFactory :初始化BeanFactory,并进行XML 文件读取(如果需要的话)。 这一步之后 ApplicationContext就具有BeanFactory 所提供的功能,也就是可以进行Bean的提取等基础操作了。
  3. prepareBeanFactory :对BeanFactory 进行各种功能填充。
  4. postProcessBeanFactory : 对 BeanFactory 做额外处理。默认没有实现
  5. invokeBeanFactoryPostProcessors : 激活各种BeanFactory 处理器(调用了各种 BeanFactoryPostProcessor )。其中最为关键的是 ConfigurationClassPostProcessor ,在这里完成了配置类的解析,生成的注入容器中的bean 的 BeanDefinition。
  6. registerBeanPostProcessors :注册和创建拦截bean创建的bean处理器。 BeanPostProcessor 在这一步已经完成了创建。
  7. initMessageSource :为上下文初始化Message 源,即对不同语言的消息体进行国际化处理
  8. initApplicationEventMulticaster :初始化应用消息广播器,并放入 "applicationEventMulticaster" bean 中
  9. onRefresh :留给子类来初始化其他bean
  10. registerListeners :在所有注册的bean中查找listener bean,注册到消息广播器中
  11. finishBeanFactoryInitialization :初始化剩下的实例(非惰性),在这里调用了getBean方法,创建了非惰性的bean实例
  12. finishRefresh :完成刷新过程,通知生命周期处理器 lifecycleProcesseor 刷新过程,同时发出 ContextRefreshEvent 通知别人。

1. 准备环境 - prepareRefresh()

prepareRefresh() 方法整体还是比较清晰的,作用就是初始化一些状态和属性,为后面的工作做准备。具体代码如下:

protected void prepareRefresh() {
   // Switch to active.
   // 设置启动时间,激活刷新状态
   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();

   // Validate that all properties marked as required are resolvable:
   // see ConfigurablePropertyResolver#setRequiredProperties
   // 准备环境变量信息
   getEnvironment().validateRequiredProperties();

   // Store pre-refresh ApplicationListeners...
   // 存储子容器早期运行的一些监听器
   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<>();
}
复制代码

这里需要注意的两个方法:

initPropertySources()
validateRequiredProperties()

我们可以通过实现或者继承 ApplicationContext 来重写这两个方法,从而完成一些基本属性的校验。

2. 加载BeanFactory - obtainFreshBeanFactory()

obtainFreshBeanFactory() 从字面意思就是获取BeanFactory。经过这个方法, BeanFactory 就已经被创建完成。具体代码如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 刷新BeanFactory,注解模式下就是准备工厂,xml模式下会解析xml
   refreshBeanFactory();
   return getBeanFactory();
}
复制代码

而实际上将 BeanFactory的创建委托给了 refreshBeanFactory() 方法, refreshBeanFactory() 方法被两个类实现 AbstractRefreshableApplicationContext 和 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值