18 April 2018

springboot版本,1.4.3.RELEASE

流水账,纯记录。

TL;DR.

  1. 创建并初始化SpringBoot实例
    1. 判断是否是web应用 : 通过是否存在Web应用相关的类来判断,javax.servlet.Servlet org.springframework.web.context.ConfigurableWebApplicationContext
    2. META-INF/spring.factories中加载ApplicationContextInitializer的实现类,为之创建实例,并按照注解Order来排序存储,getSpringFactoriesInstances
    3. META-INF/spring.factories中加载ApplicationListener的实现类,为之创建实例,并按照注解Order来排序存储,getSpringFactoriesInstances
    4. 判断应用程序主类 : 分析当前调用栈,找到含有main方法的类。不过这里只检查了方法名,若是还有其他名为main的方法,容易出现错误。
  2. 调用SpringApplication#run(String... args)启动应用程序 :
    1. META-INF/spring.factories中加载SpringApplicationRunListener的实现类,为之创建实例,并按照注解Order来排序存储,然后在启动加载的实例SpringApplicationRunListeners#started
  3. 处理命令行参数,DefaultApplicationArguments
    1. 按照是否带有前缀--来区分是否是参数选项,分别存储到CommandLineArgsoptionArgsnonOptionArgs中,参见SimpleCommandLineArgsParser#parse
  4. 准备应用程序的执行环境,prepareEnvironment
    1. 创建Environment实例,若是Web应用程序,则使用StandardServletEnvironment实例,否则使用StandardEnvironment实例。在实例化Environment时,会获取到系统变量和环境变量,放置到属性列表中。
    2. 配置创建好的Environment实例,将命令行参数中的配置项加入到属性列表中,配置profile信息,找出处理active状态的profile
    3. 调用注册的SpringApplicationRunListeners,处理environmentPrepared事件
    4. 若创建的Environment实例是ConfigurableWebEnvironment,但前面通过deduceWebEnvironment方法判断的不是Web应用,则会ConfigurableWebEnvironment实例转换为普通Environment实例
  5. 在控制台打印banner文字
  6. 创建ApplicationContext容器,对于Web应用程序,容器实例是AnnotationConfigEmbeddedWebApplicationContext。容器有两个属性,AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner,分别用来根据注解和类路径来加载Bean。注意,这时候还没有加载Bean
  7. 准备容器ApplicationContext
    1. ApplicationContextEnvironment相关联: context.setEnvironment(environment);
    2. 处理ApplicationContext实例,注册BeanBeanNameGeneratorResourceLoader
    3. 应用初始化器ApplicationContextInitializer,对ApplicationContext实例,初始化器是在初始化SpringBoot实例时加载的
    4. 调用注册的SpringApplicationRunListeners,处理contextPrepared事件
    5. 向容器ApplicationContext中注册BeanApplicationArgumentsBanner
    6. 加载应用程
    7. 调用注册的SpringApplicationRunListeners,处理contextLoaded事件
  8. 刷新容器ApplicationContext
    1. 准备刷新
      1. 清空容器属性ClassPathBeanDefinitionScanner的缓存
      2. 调用父类,执行基础准备工作
        1. 重置容器启动时间,将关闭状态置为false,将活动状态置为true
        2. 初始化属性源,若当前是Web应用,则使用GenericWebApplicationContext来初始化属性源,GenericWebApplicationContext#initPropertySources
        3. 校验必要属性是否设置
    2. 刷新BeanFactory,这里其实啥也没做
    3. 准备BeanFactory,做各项基础配置
    4. BeanFactory后续处理,这里除了做常规的后续处理之外,还会使用实例ClassPathBeanDefinitionScannerAnnotatedBeanDefinitionReader来加载应用程序的Bean
    5. 调用BeanFactoryPostProcessor
    6. 注册BeanPostProcessor
    7. 初始化MessageSource
    8. 初始化事件广播器ApplicationEventMulticaster
    9. 初始化特殊Bean
    10. 注册ApplicationListener,如果有早期事件的话,就会广播出去
    11. 实例化单例Bean
    12. 广播相关事件
  9. 刷新容器后的后续处理,这里主要是调用ApplicationRunnerCommandLineRunner完成各自的任务
  10. 调用注册的SpringApplicationRunListeners,处理finished事件