【Spring】容器刷新


title: 【Spring】容器刷新
date: 2017-07-16 00:20:31
tags:

  • Java
  • Spring
    categories: Spring

前面文章在分析 Spring Boot 的启动过程中提到了 AbstractApplicationContext 类的 refresh 方法,这个方法是 Spring 容器的核心方法之一,该方法提供了基本的模板,完成容器的初始化,并提供了丰富的接口可以从纵向(容器启动过程)、横向(不同的容器子类型)、不同形式(声明式、编程式等)进行自定义扩展。

有关 ApplicationContext 和 BeanFactory 的内容可以参考之前关于 Spring 的文章:

这里详细过一下 refresh 方法的过程,留个印象,方便以后回顾。

这篇文章就不记录关于 Spring Boot 在启动刷新阶段的特殊实现了,只关心 Spring 的通用实现模板

概览

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 刷新前准备工作
      prepareRefresh();

      // 调用子类refreshBeanFactory()方法,获取bean factory
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 创建bean Factory的通用设置
      prepareBeanFactory(beanFactory);

      try {
         // 子类特殊的bean factory设置
         postProcessBeanFactory(beanFactory);

         // 实例化beanFactoryPostProcessor
         // 调用beanFactoryPostProcessor修改bean definition
         invokeBeanFactoryPostProcessors(beanFactory);

         // 注册 bean pst processors
         registerBeanPostProcessors(beanFactory);

         // 初始化信息源,和国际化相关
         initMessageSource();

         // 初始化容器事件传播器
         initApplicationEventMulticaster();

         // 调用子类特殊的刷新逻辑
         onRefresh();

         // 为事件传播器注册事件监听器
         registerListeners();

         // 实例化所有非懒加载单例
         finishBeanFactoryInitialization(beanFactory);

         // 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
         finishRefresh();
      }

      catch (BeansException ex) {
         // ...
      }
      finally {
         // ...
      }
   }
}

刷新过程详述

prepareRefresh

protected void prepareRefresh() {
   // 设置Spring容器的启动时间,撤销关闭状态,开启活跃状态
   this.startupDate = System.currentTimeMillis();
   this.closed.set(false);
   this.active.set(true);

   if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
   }

   // 模板方法,设置属性源信息
   initPropertySources();

   // 验证环境信息里一些必须存在的属性
   getEnvironment().validateRequiredProperties();

   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

obtainFreshBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 模板方法
   // 获取刷新Spring上下文的Bean工厂
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}

prepareBeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // 设置classloader
   beanFactory.setBeanClassLoader(getClassLoader());
   // 设置表达式解析器
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   // 添加属性编辑注册器
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // 添加ApplicationContextAwareProcessor这个BeanPostProcessor用于回调
   // ApplicationContextAwareProcessor主要的作用是给实现XxxxAware的bean注入相关属性
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   // 取消以下接口的自动注入
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   // 设置特殊的类型对应的bean,修正依赖
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   // Register early post-processor for detecting inner beans as ApplicationListeners.
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   // 如果自定义的Bean中没有一个名为”loadTimeWeaver”的Bena
   // 添加一个LoadTimeWeaverAwareProcessor
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   // 如果自定义的Bean中没有名为”systemProperties”和”systemEnvironment”的Bean
   // 注册两个Bena,Key为”systemProperties”和”systemEnvironment”,Value为Map
   // 这两个bean包含系统配置和系统环绕信息
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}

postProcessBeanFactory

空实现,由具体子类实现。为子类特殊的 Application Context 实现指定特殊的 bean post 事件处理器

invokeBeanFactoryPostProcessors

整个 Spring 流程中非常重要的方法,大量的用户自定义扩展都与这个方法有关。

第一次读的时候看着怪复杂的直接跳过去了,结果启动过程的好多问题还是没搞清楚。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   // 实例化并调用所有注册的 beanFactoryPostProcessor
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

复杂的东西不在上面,是 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors 方法的调用

说明这个方法之前有两个类需要特备说明,这个方法的操作都是围绕这两个类的:

  • BeanFactoryPostProcessor

    在 bean 实例化阶段开始之前,对注册到容器的 BeanDefinition 保存的原始数据做出修改

  • BeanDefinitionRegistryPostProcessor

    继承自上面的 BeanFactoryPostProcessor

    专门用来对注册的容器的 BeanFactoryPostProcessor 的BeanDefinition 保存的原始数据做出修改

有点拗口,不过意思类似指针与二级指针的关系。

整个 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors 的实现太复杂了,但其实就一个意思:

  1. 先用 BeanDefinitionRegistryPostProcessor 修改 BeanFactoryPostProcessor 的 BeanDefinition
  2. 然后用 BeanFactoryPostProcessor 修改普通的 BeanDefinition

具体在操作过程中 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor 执行的顺序有明确的限制,两者都是根据以下规则执行:

  1. 首先执行实现 PriorityOrdered 接口的,调用顺序是按照接口方法 getOrder() 的实现
  2. 其次执行实现 Ordered 接口的,调用顺序是按照接口方法 getOrder() 的实现
  3. 最后执行既没有实现 PriorityOrdered 也没有实现 Ordered 的,调用顺序是 bean 的定义顺序

registerBeanPostProcessors

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   // 从Spring容器中找出的BeanPostProcessor接口的bean,并设置到BeanFactory的属性中
   PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

思路与 invokeBeanFactoryPostProcessors 方法类似。

但只是从容器中找出实现 BeanPostProcessor 的bean,排序后设置到BeanFactory的属性中,并不调用。

具体的排序过程:

  1. 优先调用 PriorityOrdered 接口的子接口,调用顺序依照接口方法getOrder的返回值从小到大排序
  2. 其次调用Ordered接口的子接口,调用顺序依照接口方法getOrder的返回值从小到大排序
  3. 接着按照 BeanPostProcessor 实现类在配置文件中定义的顺序进行调用
  4. 最后调用MergedBeanDefinitionPostProcessor接口的实现Bean,同样按照在配置文件中定义的顺序进行调用

initMessageSource

protected void initMessageSource() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
      // 如果自定义了名为”messageSource”的Bean
      // 直接实例化Bean,该Bean必须是MessageSource接口的实现Bean
      // 该Bean如果是HierarchicalMessageSource接口的实现类
      // 强转为HierarchicalMessageSource接口,并设置一下parentMessageSource
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      // Make MessageSource aware of parent MessageSource.
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         if (hms.getParentMessageSource() == null) {
            // Only set parent context as parent MessageSource if no parent MessageSource
            // registered already.
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
      if (logger.isDebugEnabled()) {
         logger.debug("Using MessageSource [" + this.messageSource + "]");
      }
   }
   else {
      // 如果没有自定义名为”messageSource”的Bean,那么会默认注册一个DelegatingMessageSource并加入
      // Use empty MessageSource to be able to accept getMessage calls.
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
      if (logger.isDebugEnabled()) {
         logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
               "': using default [" + this.messageSource + "]");
      }
   }
}

initApplicationEventMulticaster

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      // 如果自定义了名为”applicationEventMulticaster”的Bean
      // 实例化自定义的Bean,自定义的Bean必须是ApplicationEventMulticaster接口的实现类
      this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isDebugEnabled()) {
         logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
   }
   else {
      // 如果没有自定义名为”ApplicationEventMulticaster”的Bean
      // 注册一个类型为SimpleApplicationEventMulticaster的Bean
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isDebugEnabled()) {
         logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
               APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
               "': using default [" + this.applicationEventMulticaster + "]");
      }
   }
}

onRefresh

空的模板方法,根据不同的 ApplicationContext 子类实现对应的业务逻辑

registerListeners

protected void registerListeners() {
   // Register statically specified listeners first.
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // Do not initialize FactoryBeans here: We need to leave all regular beans
   // uninitialized to let post-processors apply to them!
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   // Publish early application events now that we finally have a multicaster...
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   //有容器转换服务bean时先实例化这种Bean
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }
   
   // 注册一个默认的嵌入式值解析器
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
         @Override
         public String resolveStringValue(String strVal) {
            return getEnvironment().resolvePlaceholders(strVal);
         }
      });
   }

   // 实例化LoadTimeWeaverAware类型Bean
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // 停止使用临时类加载器
   beanFactory.setTempClassLoader(null);

   // 缓存容器中所有注册的BeanDefinition元数据,以防被修改
   beanFactory.freezeConfiguration();

   // 实例化剩余的所有非lazy-init singleton Bean
   beanFactory.preInstantiateSingletons();
}

finishRefresh

protected void finishRefresh() {
   // 初始化生命周期处理器(LifecycleProcessor)
   // 先找一下有没有自定义名为lifecycleProcessor的Bean,有的话就实例化出来
   // 该Bean必须是LifecycleProcessor的实现类
   // 没有则向Spring上下文中注册一个类型为DefaultLifecycleProcessor的LifecycleProcessor实现类
   initLifecycleProcessor();

   // 调用生命周期处理器的onRefresh方法
   getLifecycleProcessor().onRefresh();

   // 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作
   publishEvent(new ContextRefreshedEvent(this));

   // 如果设置了JMX相关的属性,则就调用该方法
   LiveBeansView.registerApplicationContext(this);
}

以上就是简单的记录了 Spring 启动过程中容器刷新的动作。


以上内容除了源码的阅读还参考了其他博客,学习到了很多细节,这里表示感谢了:

SpringBoot源码分析之Spring容器的refresh过程

Spring-- Ioc 容器Bean实例化的几种场景

《Spring技术内幕》学习笔记6——IoC容器的高级特性

Spring源码分析:非懒加载的单例Bean初始化前后的一些操作

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339

推荐阅读更多精彩内容

  • 1.1 spring IoC容器和beans的简介 Spring 框架的最核心基础的功能是IoC(控制反转)容器,...
    simoscode阅读 6,689评论 2 22
  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 6,923评论 4 21
  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,427评论 1 133
  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 2,791评论 1 24
  • 朋友安利这款APP,偶然安装上,觉得真心不错,所以也来凑凑热闹。 每一天的生活仿佛都会有很多事情穿插进来,所以才会...
    陈昂昂昂昂昂阅读 177评论 0 0