run(args)
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
//1:获取并启动监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//2:项目运行环境Environment的配置,比如:dev、test、prod等等
//创建ApplicationArguments对象:初始默认应用参数。args是项目启动时传入的参数 比如:--spring.profiles.active=dev
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印banner
Banner printedBanner = printBanner(environment);
//3:创建并初始化spring容器
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//4:容器的前置处理
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//5:刷新容器,初始化容器中的bean
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
//通知listener。上下文启动完成
listeners.started(context, timeTakenToStartup);
//服务启动之后执行application runner中的方法(可自定义runner)
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
//至此,项目启动完成
return context;
}
不着急,一行一行的看
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
这是干嘛的?遇见这种新代码,先别着急看代码逻辑,因为你大概可能也许 是看不明白的。
先看git blame
Refactor BootstrapRegistry support
RefactorBootstrapRegistry
support following initial prototype work with the Spring Cloud team.
看来是可能和SpringCloud有点关系,很好,那就不需要关注了。
run(args)做的事情
1:启动监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
getRunListeners(args)
这个方法是获取的SpringApplicationRunListener
这个接口的实例。
那么看下spring.factories
中配置的此接口默认实现是什么
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
也就是说默认实现就是EventPublishingRunListener
接着看下边这一行做了什么
listeners.starting(bootstrapContext, this.mainApplicationClass);
看一下starting
实现是什么
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
主要看这一行其实就可以了
(listener) -> listener.starting(bootstrapContext)
starting()
就不看了,对spring有点了解的其实可以猜出来,这就是spring event的那些东西。
感兴趣的可以看下这篇文章。
总结
启动监听器,广播消息:spring boot开始启动。
2:配置运行环境Environment
//创建ApplicationArguments对象:初始默认应用参数。args是项目启动时传入的参数 比如:--spring.profiles.active=dev
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
3:创建spring容器
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
4:容器的前置处理,准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
prepareContext
里边得看下applyInitializers(context);
上一篇SpringBoot启动的时候做了什么(1)中讲了在初始化SpringApplication
的时候,有一步是初始化Initiallizers
,当时没讲是用来做什么的,这里就用到了。
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
上边的这个setInitiallizers()
内部实现是这样的:
public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {
this.initializers = new ArrayList<>(initializers);
}
那其实就是对this.initializers
赋值。
接着讲回prepareContext
里边的applyInitializers(context);
这个方法,其实一看就是和创建SpringApplication
时,初始化的this.initializers
有关系
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
这个方法里其实就是做了两步
- 获取所有的
Initiallizer
- 执行
initializer.initialize
,initializer
在上边文章中说过有哪些了,就不深入看了
5:刷新容器,初始化bean
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
//向JVM注册一个关闭钩子,当JVM关闭时,会调用ApplicationContext的close方法。
shutdownHook.registerApplicationContext(context);
}
//刷新上下文。其实就是完成了对整个IOC容器的初始化(bean资源的定位、解析、注册等)
refresh(context);
}
6:完成启动,listener广播、执行application runner
//通知listener。上下文启动完成
listeners.started(context, timeTakenToStartup);
//服务启动之后执行application runner中的方法(可自定义runner)
callRunners(context, applicationArguments);
总结
其实整个启动的过程就是几个关键词
- 运行环境:
Environment
- 监听器:
Listener
- 初始化器:
Initializer
- 容器实例化:
ApplicationContenxt
- IOC初始化:
refresh()
后边有时间再写一下IOC初始化的过程。