Spring -- refresh()方法流程梳理

1,765 阅读5分钟

前言

最近在阅读spring源码,refresh这个方法的处理流程每次看都会有一点新的认识。本文章是自己对这一块源码功能的梳理记录。文章只对这一块代码的主要流程做一个梳理,需要对以下类有一定的认识。

  • PropertySources
  • BeanFactory
  • DefaultListableBeanFactory
  • ConfigurableListableBeanFactory
  • BeanDefinitionRegistry
  • BeanDefinition
  • BeanFactoryPostProcessor
  • BeanPostProcessor 另外,本文是基于springboot工程启动时梳理的spring的加载过程,有些实现类是springboot提供的。下面放一张类关系图。其中AnnotationConfigServletWebServerApplicationContext和ServletWebServerApplicationContext由springboot提供。

annotation.png

refresh整体结构

下面的代码是从AbstractApplicationContext类中摘下来的,只保留了关键处理流程。Spring启动时会执行这个方法,主要流程就是try代码块中的几个方法。里面的功能包含:

  1. Ioc容器初始化
  2. 对扫描到的class进行封装
  3. bean的实例化、属性填充、初始化、扩展点方法的调用
  4. AOP包装
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
      prepareRefresh();
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      prepareBeanFactory(beanFactory);

      try {
         postProcessBeanFactory(beanFactory);
         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         invokeBeanFactoryPostProcessors(beanFactory);
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();
         initMessageSource();
         initApplicationEventMulticaster();
         onRefresh();
         registerListeners();
         finishBeanFactoryInitialization(beanFactory);
         finishRefresh();
      } catch (BeansException ex) {
         destroyBeans();
         cancelRefresh(ex);
         throw ex;
      } finally {
         resetCommonCaches();
         contextRefresh.end();
      }
   }
}

流程梳理

1. prepareRefresh

清理scanner的缓存,初始化PropertySources,校验环境中的一些关键属性。

2. obtainFreshBeanFactory

springboot启动时,beanFactory是在refresh执行之前创建的,这里直接返回。

3. prepareBeanFactory(beanFactory)

设置一些ioc容器加载时必须使用的 BeanPostProcessor 和 register。

4. postProcessBeanFactory(beanFactory)

根据我的上下文,是进入AnnotationConfigReactiveWebServerApplicationContext中,啥也没做。

5.invokeBeanFactoryPostProcessors(beanFactory)

  • 主要流程
  1. 调用 BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,扫描class,封装成BeanDefinition。分三次调用,第一次时实现PriorityOrdered接口的,第二次是实现 Ordered 接口的,第三次是其他的所有注册器,例如mybatis的注册器。
  2. 调用 BeanFactoryPostProcessor的postProcessBeanFactory方法,在bean创建之前,修改bean的定义属性。分三次调用,第一次时实现PriorityOrdered接口的,第二次是实现 Ordered 接口的,第三次是其他的。
  • 关键类功能
  1. ConfigurationClassPostProcessor:从启动类开作为入口,解析 @Configuration 标记的类。扫描出来的class后边会遍历进行处理。
  2. ClassPathBeanDefinitionScanner:doScan方法干活,把能读取到的class文件中使用了@Component注解的类都封装成BeanDefinition。@Bean注解标记的class,判断scope是否需要创建代理对象。
  3. ConfigurationClassParser:doProcessConfigurationClass方法解析当前类,把@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean、接口方法、super类方法都进行处理。需要注册的bean统统管理在beanFactory中。
  • 扩展点
  1. @Import、@ImportResource注解。在执行到这两个注解的处理时可以把自定义的对象导入到spring容器中。
  2. BeanDefinitionRegistryPostProcessor接口。实现类放到spring中之后,spring会调用对应的postProcessBeanDefinitionRegistry,实现自定义对象的注册。

6. registerBeanPostProcessors(beanFactory)

  • 主要流程 通过前面的扫描和注册,spring能管理的bean都已经被读取出来了。这里找出实现了BeanPostProcessor接口的类,按优先级排序后注册起来。优先级从高到低依次是实现PriorityOrdered接口的,实现 Ordered 接口的,没优先级和order顺序的,internal的。

7. initMessageSource

国际化处理

8. initApplicationEventMulticaster

初始化一个事件广播器,注册到beanFactory中。

9. onRefresh

  • 功能 我们这里分析的是web应用,这里会使用内置的tomcat创建一个webserver。

10. registerListeners

注册listener

11. finishBeanFactoryInitialization(beanFactory)

  • 主要流程 实例化非延迟加载的bean实例
  1. 遍历所有的beanName,通过getBean去创建需要加载的bean。涉及实例化、填充、初始化三个阶段。
  2. 再遍历所有的beanName,找到SmartInitializingSingleton类型的bean,调用它的afterSingletonsInstantiated方法。
  • getBean()处理过程
  1. Object sharedInstance = getSingleton(beanName); 先获取一次
  2. markBeanAsCreated(beanName); 放到已经创建的列表,做标记用
  3. getSingleton(String beanName, ObjectFactory<?> singletonFactory); 再获取一次,没有的话调用singletonFactory.getObject()创建
  4. createBean(beanName, mbd, args); // 这就是上面的创建具体实现
  5. doCreateBean(beanName, mbdToUse, args);//真正的创建方法
  6. populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw); // 这里会触发InstantiationAwareBeanPostProcessor中postProcessPropertyValues的调用
  7. initializeBean(beanName, exposedObject, mbd);// 1、触发BeanPostProcessor的postProcessBeforeInitialization 2、触发InitializingBean的afterPropertiesSet 3、触发BeanPostProcessor的postProcessAfterInitialization的调用
  • 循环依赖解决
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      singletonObject = this.earlySingletonObjects.get(beanName);
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     singletonObject = singletonFactory.getObject();
                     // 把自己暴露在二级缓存中
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     // 从一级缓存中删除
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}
protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}
// 走到这里,bean已经创建完成
protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName); // 删除
      this.earlySingletonObjects.remove(beanName); // 删除
      this.registeredSingletons.add(beanName);
   }
}
  • 关键类的功能
  1. AutowiredAnnotationBeanPostProcessor:对@Autowired注解标记的对象进行注入
  2. DefaultSingletonBeanRegistry 注册bean,解决循环依赖
  • 扩展点
  1. BeanPostProcessor
  2. InitializingBean
  3. InstantiationAwareBeanPostProcessor

12. finishRefresh

发布ContextRefreshedEvent事件

关于AOP

@EnableAspectJAutoProxy开启Aop,里面导入AspectJAutoProxyRegistrar类,这个类会注入一个AnnotationAwareAspectJAutoProxyCreator类,这个类是BeanPostProcesser接口的一个实现类,在initializeBean执行前后会执行接口总的实现方法,实现代理的效果。

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

下面放一个AOP的类关系图:

aop.png

总结

  1. Spring先对beanFactory进行初始化工作
  2. 以启动类作为入口,扫描出所有可以读取到的class
  3. 对扫描出来的class进行解析,继续扫描出所有需要管理的class,全部封装为beanDefinition
  4. 找出所有的BeanPostProcessor并注册
  5. 遍历所有的beanName,实例化需要提前加载的bean。这里包括实例化、自动注入、初始化三个阶段。同时处理了循环依赖问题。每个阶段还包括对扩展点的调用。