SpringBoot启动流程简析(二)

前面分析了SpringBoot启动时,创建SpringApplication实例的流程,接下里分析调用SpringApplication的run()方法的主要执行流程。

代码入口:
SpringApplication.run(String… args)方法

public ConfigurableApplicationContext run(String... args) {
        //监控SpringApplication启动耗时
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		
		//Spring上下文
		ConfigurableApplicationContext context = null;
		//SpringBoot异常上报处理器
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//设置无头模式
		configureHeadlessProperty();
		
		//从spring.factories中获取SpringBoot启动过程中配置的相关事件的监听器集合
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//触发SpringApplicationRunListener的starting()方法
		listeners.starting();
		
		try {
		     // Provides access to the arguments that were used to run a {@link SpringApplication}.
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
					
			//Spring上下文创建前,创建环境变量对象
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
			//输出Banner信息    
			Banner printedBanner = printBanner(environment);
			//创建Spring应用上下文
			context = createApplicationContext();
			//创建SpringBoot异常上报器
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//refresh上下文之前的准备,并触发SpringApplicationRunListener的contextPrepared()方法		
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			//refresh上下文		
			refreshContext(context);
			//refresh上下文之后的处理
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			//触发Spring容器启动完成事件
			listeners.started(context);
			//从SpringContext中获取ApplicationRunner,CommandLineRunner的实例并调用
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
		    //触发Spring容器运行事件
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		//至此,SpringBoot启动完成,返回Spring上下文
		return context;
	}

总体流程如上,后续会就相关重要细节分析下。本章留意下SpringApplicationRunListener接口的各个方法都是在SpringBoot启动流程中哪些地方被调用的。

public interface SpringApplicationRunListener {

	/**
	 * Called immediately when the run method has first started. Can be used for very
	 * early initialization.
	 */
	void starting();

	/**
	 * Called once the environment has been prepared, but before the
	 * {@link ApplicationContext} has been created.
	 * @param environment the environment
	 */
	void environmentPrepared(ConfigurableEnvironment environment);

	/**
	 * Called once the {@link ApplicationContext} has been created and prepared, but
	 * before sources have been loaded.
	 * @param context the application context
	 */
	void contextPrepared(ConfigurableApplicationContext context);

	/**
	 * Called once the application context has been loaded but before it has been
	 * refreshed.
	 * @param context the application context
	 */
	void contextLoaded(ConfigurableApplicationContext context);

	/**
	 * The context has been refreshed and the application has started but
	 * {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
	 * ApplicationRunners} have not been called.
	 * @param context the application context.
	 * @since 2.0.0
	 */
	void started(ConfigurableApplicationContext context);

	/**
	 * Called immediately before the run method finishes, when the application context has
	 * been refreshed and all {@link CommandLineRunner CommandLineRunners} and
	 * {@link ApplicationRunner ApplicationRunners} have been called.
	 * @param context the application context.
	 * @since 2.0.0
	 */
	void running(ConfigurableApplicationContext context);

	/**
	 * Called when a failure occurs when running the application.
	 * @param context the application context or {@code null} if a failure occurred before
	 * the context was created
	 * @param exception the failure
	 * @since 2.0.0
	 */
	void failed(ConfigurableApplicationContext context, Throwable exception);

}

具体可以查看org.springframework.boot.SpringApplicationRunListeners的实现。

总结:
SpringApplication.run(String… args)方法的主要流程:
(1) 从spring.factories中获取SpringBoot启动过程中配置的相关事件的监听器集合;
(2) 创建ApplicationArguments实例,为SpringApplication运行提供参数获取;
注意:是main方法参数,不是环境变量。
(3) 创建Spring上下文环境变量ConfigurableEnvironment的实例;
(4) 控制台打印Spring的Banner信息;
(5) 创建Spring上下文实例,接口类型是ConfigurableApplicationContext,默认的实例是:

org.springframework.context.annotation.AnnotationConfigApplicationContext

(6) 从spring.factories中获取SpringBootExceptionReporter异常处理器集合;
(7) 刷新Spring上下文前的相关处理;
(8) 刷新Spring上下文;
(9) 打印SpringBoot启动完成的耗时等相关日志信息;
(10) 从Spring上下文中获取ApplicationRunner,CommandLineRunner的实例并调用;
(11) 返回ConfigurableApplicationContext对象,至此SpringBoot启动完成;

上述过程中,隐去了SpringBoot启动过程中,相关监听器SpringApplicationRunListener实例集合的调用,具体查看SpringApplicationRunListener类。

后续将着重分析SpringBoot启动过程中,对Spring上下文的处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值