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。
去打赏