SpringBoot启动的时候做了什么(2)

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
Refactor BootstrapRegistry 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);
	}
}

这个方法里其实就是做了两步

  1. 获取所有的Initiallizer
  2. 执行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初始化的过程。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值