【源码】简单看SpringBoot启动过程
 doctorrm      2019-07-25 14:18:30      30      0      

SpringBoot最简单的启动类如下。通过该启动类,Java线程可以启动并维持一个进程(如tomcat进程),用于处理相应请求。

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);//从这行出发探讨
    }
}

实际上,上述中的run()方法是将DemoApplication转为SpringApplication,再调用SpringApplication的run(args)方法,去掉异常、打印日志等次要信息后,得到【简化版】代码:

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();//启动计时器
        ConfigurableApplicationContext context = null;
        SpringApplicationRunListeners listeners = getRunListeners(args);//根据参数获取Spring应用监听器
        listeners.starting();//启动监听器,监听器处于监听状态
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);//监听器+参数-->准备运行环境
        Banner printedBanner = printBanner(environment);//控制台打印banner,即控制台打印经典的《Spring》
        context = createApplicationContext();//创建应用上下文
        // 准备、刷新上下文(使用到了监听器和环境)
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        stopWatch.stop();//停止计时器
        listeners.started(context);//监听器启动上下文,启动但还未运行
        callRunners(context, applicationArguments);
        listeners.running(context);//监听器运行上下文
        return context;
}

该方法用到两个类:SpringApplicationRunListenersStopWatch,分别与监听器和计时器相关,SpringBoot通过监听器SpringApplicationRunListeners来启动CPU进程并使项目保持运行状态,并通过计时器StopWatch来统计启动时间。

从代码逻辑看,监听器参与了运行环境和上下文的逻辑过程,而运行环境又参与了上下文的逻辑过程。最后通过监听器运行上下文运行项目,并返回上下文,从中可知,上下文是关键。

以上就是SpringBoot启动的简化版过程。

另外,上面提到的监听器是run方法专属的监听器,每调用一次run()方法,就会创建一个监听器SpringApplicationRunListener(注意名称中的Run)。该监听器是一个接口,提供了启动相关的接口方法,比如starting(),started(),running(),failed(),contextLoaded()等,启动时会通过其实现类来执行具体过程。那在哪里实现了监听器接口呢?就在run()方法代码中的:

SpringApplicationRunListeners listeners = getRunListeners(args);//根据参数获取Spring应用监听器

这里根据参数args来实例化监听器集合,getRunListeners()方法是个私有方法,通过构造器实例化监听器集合:

private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class[] types = new Class[] { SpringApplication.class, String[].class };
    return new SpringApplicationRunListeners(logger,
            getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

再具体点,构造器参数的getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)返回了一个监听器实现类,抽象来看,该方法“告诉“Spring实例工厂: “我给你这些args参数,请给我一个SpringApplicationRunListener.class类型的实例“,创建监听器实例的工作就由Spring的实例工厂负责了。而Spring实例工厂如何通过参数和类加载器创建一个个的实例,就和启动过程无关了,因此暂不在本文范围内。

实际上到了这里,对于SpringBoot的启动过程,我们只是到了源码的表层,至于监听器实例如何启动和运行上下文、如何读取配置文件等具体细节,SpringBoot做了大量的封装,本文也没能深入到这个层次。但看完本文,你可以在源码的层次理解:SpringBoot的启动需要若干类的参与,其中的监听器经过Spring工厂实例化后,通过操纵应用上下文来启动SpringBoot。

去打赏

您的支持将鼓励我们继续创作!

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

正在跳转到PayPal...

发表评论