SpringBoot启动配置原理解析

版权声明:版权所有,翻版我也没办法!!! https://blog.csdn.net/tebtebtebteb/article/details/82817478

今天来简单的说一下关于SpringBoot的启动流程,在整个启动配置中,有几个比较重要的事件回调机制需要特别注意,先列出:

  • ApplicationContextInitializer
  • SpringApplicationRunListener
  • ApplicationRunner
  • CommandLineRunner

下面的代码是SpringBoot的启动类

@SpringBootApplication
public class SpringBoot06DataJpaApplication {

	public static void main(String[] args) {

		SpringApplication.run(SpringBoot06DataJpaApplication.class, args);
	}
}

进入run()方法中查看:

 public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
        return (new SpringApplication(sources)).run(args);
    }

从run()方法中可以看出,run()方法的启动分为两步:

  • 创建SpringApplication对象
  • 运行run()方法

下面分析这两步具体做了什么。

1.创建SpringApplication对象

  public SpringApplication(Object... sources) {
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.initialize(sources);
    }

执行SpringApplication的构造方法,创建对象,接着执行initialize()初始化方法

​
​
 private void initialize(Object[] sources) {
//保存主配置类
   if (sources != null && sources.length > 0) {
       this.sources.addAll(Arrays.asList(sources));
    }
//判断当前应用是否为web应用
 this.webEnvironment = this.deduceWebEnvironment();

//从类路径下找到META_INF/spring.factories配置的所有ApplicationContextInitializer,并保存 
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

 //从类路径下找到META_INF/spring.factories配置的所有ApplicationListener,然后保存起来
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

//从多个配置类中找到有main方法的主配置类
this.mainApplicationClass = this.deduceMainApplicationClass();

}

​

​
  • //从类路径下找到META_INF/spring.factories配置的所有ApplicationContextInitializer,例如:

点击进入spring.factories

进入setInitializers()方法中,可以查看在当前项目中找到的ApplicationContextInitializer的个数

同理, //从类路径下找到META_INF/spring.factories配置的所有ApplicationListener,然后保存起来
 

至此,SpringApplication对象创建完毕。

2.执行run()方法

public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   this.configureHeadlessProperty();

   //从类路径下的META-INF/spring.factories中获取SpringApplicationRunListeners 
   SpringApplicationRunListeners listeners = this.getRunListeners(args);

   //回调所有的获取SpringApplicationRunListener.starting()方法
   listeners.starting();

try {

   //封装命令行参数
   ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

   //准备环境(进入prepareEnvironment()方法中可以看到创建环境完成后将回调
   SpringApplicationRunListeners的environmentPrepared()方法,表示环境准备完成 )
   ConfigurableEnvironment environment = this.prepareEnvironment(listeners, 
   applicationArguments);

   //环境准备好之后就打印printBanner(即SpringBoot的在启动时的logo)
   Banner printedBanner = this.printBanner(environment);
   //创建一个ApplicationContext IOC容器,主要是决定创建web的ioc还是普通的ioc
   context = this.createApplicationContext();

   new FailureAnalyzers(context);
   
   //准备上下文环境,将environment保存到ioc中,而且要执行applyInitializers()方法;
   //applyInitializers():回调上面说到的所有的ApplicationContextInitializer的
   // initialize()方法;此外,还要回调前面说到的所有的SpringApplicationRunListener的
   // contextPrepared()方法
   this.prepareContext(context, environment, listeners, applicationArguments, 
   printedBanner);

   //刷新容器:ioc容器初始化(如果是web应用,还会创建嵌入式的Tomcat容器)
   this.refreshContext(context);
   //从IOC容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
   //ApplicationRunner先回调,CommandLineRunner后回调,有优先级。
   this.afterRefresh(context, applicationArguments);
   //所有的SpringApplicationRunListener回调finished()方法
   listeners.finished(context, (Throwable)null);

   stopWatch.stop();

  if (this.logStartupInfo) {
       (new StartupInfoLogger(this.mainApplicationClass)).logStarted
       (this.getApplicationLog(), stopWatch);
   
    }
   //整个SpringBoot应用启动完成以后返回启动的IOC容器
   return context;

   } catch (Throwable var9) {
         this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
         throw new IllegalStateException(var9);
     }
 }

猜你喜欢

转载自blog.csdn.net/tebtebtebteb/article/details/82817478