Spring Boot的初始化过程

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 Listeners
org.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.0 Start UserApp Run SpringApplication Run create & prepare APP context refresh context callRunners End
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值