Spring Boot的初始化过程

来源:互联网 发布:免费服装店收银软件 编辑:程序博客网 时间:2024/06/06 20:09

Spring Boot的初始化过程

Spring Boot是开发微服务的不二利器。它遵从Convention over Configuration原则,看上去非常简约,但实际底下却做了很多工作。本文从Spring Boot应用程序的初始化过程入手,讲解一下其实现细节。
一般Spring Boot的应用都是从main函数开始,调用SpringApplication.run函数。

SpringApplication.run(SomeApp.class, args);

这是一个静态函数,实际上它构造了一个SpringApplicaiton的实例,并调用另外一个run方法,如下所示:

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {    return new SpringApplication(sources).run(args);}public SpringApplication(Object... sources) {    // 一系列的初始化    initialize(sources);}private void initialize(Object[] sources) {    if (sources != null && sources.length > 0) {        this.sources.addAll(Arrays.asList(sources));    }    // 判断是否为Web应用, 依据是此时是否已加载Servlet或ConfigurableWebApplicationContext类    this.webEnvironment = deduceWebEnvironment();    // 设置初始化对象,后期在prepareContext时调用    setInitializers((Collection) getSpringFactoriesInstances(            ApplicationContextInitializer.class));    // 设置应用监听器,注意与后面的应用运行情况监听器区别    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));    // 获取当前应用的主类,及带有入口函数main的类    this.mainApplicationClass = deduceMainApplicationClass();}public ConfigurableApplicationContext run(String... args) {    StopWatch stopWatch = new StopWatch();   ----- (1)    stopWatch.start();    ConfigurableApplicationContext context = null;    FailureAnalyzers analyzers = null;    configureHeadlessProperty();    SpringApplicationRunListeners listeners = getRunListeners(args); ----- (2)    listeners.starting();    try {        ApplicationArguments applicationArguments = new DefaultApplicationArguments(                args);   ----- (3)        ConfigurableEnvironment environment = prepareEnvironment(listeners,                applicationArguments);    ----- (4)        // 打印spring标志        Banner printedBanner = printBanner(environment);        // 创建应用上下文对象        context = createApplicationContext();        analyzers = new FailureAnalyzers(context);   ----- (5)        prepareContext(context, environment, listeners, applicationArguments,                printedBanner);      ----- (6)        refreshContext(context);        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);    }}

1. StopWatch

StopWatch是Spring Framework的一个辅助类,它的作用是记录曾经执行的一系列任务,并在这些任务结束时统计其运行的时间。StopWatch有一个函数名叫prettyPrint,一听就知道它会做一些漂亮的输出工作,例如:

 -----------------------------------------    ms     %     Task name    -----------------------------------------    02000  020%  initializing    05000  050%  processing    03000  030%  finalizing

一般Spring Boot程序启动完成后都会输出整个启动过程花了多长时间,这个任务就是由StopWatch来完成的。

2. SpringApplicationRunListeners

这是一个Spring应用运行情况监听类的集合类。这句话比较拗口,实际上它就是将一些事件监听对象集合在一起的类,这些对象都继承自SpringApplicationRunListener接口。从名字上就可以判断出它们是用于监听应用的运行情况的。具体监听哪些事件,查看一下接口的定义就一目了然了。

public interface SpringApplicationRunListener {    // 应用开始启动    void starting();    // 环境变量准备完毕    void environmentPrepared(ConfigurableEnvironment environment);    // 上下文对象准备完毕    void contextPrepared(ConfigurableApplicationContext context);    // 上下文对象加载完毕    void contextLoaded(ConfigurableApplicationContext context);    // 应用启动结束    void finished(ConfigurableApplicationContext context, Throwable exception);}

Spring Boot调用getRunListeners(args),从ClassPath中搜寻该接口的实现类,实例化,并将结果保存在这个监听对象集合类里。不过并不是所有实现类都会被实例化,只有在ClassPath中所有“META-INF/spring.factories”文件中声明的实现类才会被实例化。默认情况下,这个接口只在spring-boot-.jar包里的“META-INF/spring.factories”声明,内容如下:

# Run Listenersorg.springframework.boot.SpringApplicationRunListener=\org.springframework.boot.context.event.EventPublishingRunListener

这个文件里还有很多其他配置。可见,虽然Spring Boot的架构原则是Convenience Over Configuration, 但是并非绝对,仍然还有一些配置。

获取监听器之后,调用listeners.starting( ),即可执行这些监听器的starting方法。

3. ApplicationArguments

这是Spring Boot提供的处理应用参数的接口,同时Spring Boot还提供了一个实现类DefaultApplicationArguments。使用起来非常直白,只要在构造时代入参数args,使用时只要getOptionNames,getOptionValues即可。

4. ConfigurableEnvironment

读取各种环境变量,包括系统环境变量,JVM的属性,以及web servlet容器的属性等等。

5. FailureAnalyzers

失败分析器。这跟ApplicationRunListeners类似,也是根据spring.factories里的配置生成相应的对象。

6. prepareContext

这里主要是对应用的上下文对象进行初始化,应用初始化对象(SpringApplication构造时获取的那些初始化对象,定义在spring.factories里),加载bean等等。

Created with Raphaël 2.1.0StartUserApp RunSpringApplication Runcreate & prepare APP contextrefresh contextcallRunnersEnd
0 0