【源码】简单看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;
}

该方法用到两个类:SpringApplicationRunListeners和StopWatch,分别与***和计时器相关,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


全部评论

相关推荐

10-09 09:39
门头沟学院 C++
HHHHaos:这也太虚了,工资就一半是真的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务