Springboot启动原理(二)

一、启动方法

二、进入run方法,跟踪下去发现他先调用一个初始化方法initialize

①sources 就是你的启动对象

②deduceWebEnvironment()判断是否是web环境,原理就是判断如下的两个类是否存在,存在就是web环境

③getSpringFactoriesInstances方法在springboot里大量使用,他的作用是从spring的autoconfig包里的META-INF下的spring.factories文件中加载指定接口的所有实现类。例如:getSpringFactoriesInstances(ApplicationContextInitializer.class)这句代码,实际是去加载如下的类

④setInitializers 把加载到的类放到一个list里头去

⑤setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));这行代码原理同③④,不做重复讲解

⑥deduceMainApplicationClass 作用是获取启动类

三、看完初始化方法,接下来就是调用run方法了

public ConfigurableApplicationContext run(String... args) {
   //时钟工具,用来计时
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   //ApplicationContext的子类,比父类拥有更加丰富的方法,具体的以后分享spring原理的时候再说
   ConfigurableApplicationContext context = null;
   //异常报告,后面调用时候详细说明
   FailureAnalyzers analyzers = null;
   //设置无头模式,我也不太懂,自行百度,好像说是让电脑自己模拟外接设备
   configureHeadlessProperty();
   //去spring.factories里加载SpringApplicationRunListener接口的实现类,其实这里说是listener,实际上SpringApplicationRunListener更像一个发布者publish,他的作用是发布各自事件
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //spring的观察者模式模板,在springboot启动过程用了很多这样通知的地方,下一章将用一章来讲解各个listener
   listeners.starting();
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      //这一步获取启动命令里的配置和具体要使用哪个环境的配置文件,就是根据sprring.active.profiles来加载配置文件。但是这里要注意命令里的配置会记录到enviroment里,但是配置文件,该行代码仅仅是记录你是用哪个文件。(说得够清楚了吧)
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      //打印banner
      Banner printedBanner = printBanner(environment);
      //根据是否是web项目创建不同的applicationcontext
      context = createApplicationContext();
      //这儿也是去spring.factories里加载好多失败分析器,这个也单独拿一个篇幅讲吧。这篇主要是通体脉络,细节会拆分到各个子篇幅里去讲。
      analyzers = new FailureAnalyzers(context);
      //这里会把我们之前初始化时候加载的初始化类都执行一遍,后面专门开一个讲每个初始化类的作用
      //以及会把启动类加载到spring容器里去,这样我们第一章讲的注解就能生效了。
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      //调用spring的refresh方法
      refreshContext(context);
      //查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行它们。
      afterRefresh(context, applicationArguments);
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章