【springboot源码解读系列】(二、springboot创建SpringApplication实例后,正式启动之前的准备工作)

上一节:【springboot源码解读系列】(一、springboot创建SpringApplication实例,定制SpringApplication)讲到了创建SpringApplication实例时,springboot做的一些事情:设置基础资源、推断应用程序的环境、通过SpringFactories加载我们自定义的初始化器和监听器、推断主入口类
创建完实例之后,调用了run方法开始运行。

在实际开始工作之前需要做一些准备工作,就像我们上班一样,在开始写代码之前,需要做一些比如打开电脑,编辑器,抽支烟等一系列准备工作,那么springboot也同样如此。

	/**
	 * 运行spring运行程序,创建并且刷新一个新的上下文环境:ApplicationContext
	 * 应用程序参数(通常从Java主方法传递)
	 */
	public ConfigurableApplicationContext run(String... args) {
		// 创建一个简单的秒表实例(其实并不简单)
		StopWatch stopWatch = new StopWatch();
		// 开始计时,内部使用的是System.nanoTime(),纳秒级别的
		stopWatch.start();
		// 声明一个上下文实例:context,并且复制为null
		ConfigurableApplicationContext context = null;
		// 创建一个SpringBootExceptionReporter集合。他是用于定制异常报告的,
		// 简单点来说,我们可以对抛出的异常进行定制化输入,
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		// 设置无头属性:java.awt.headless,
		// 该应用程序,即使没有检测到显示器,也允许其启动.
		// 对于服务器来说,是不需要显示器的,所以要这样设置.
		configureHeadlessProperty();
		// 获取所有的spring应用启动监听器,同样也是通过SpringFactoriesLoader获取的监听器
		// 并将其方式SpringApplicationRunListeners中的listeners属性中,他是使用final修饰的,
		// 在调用SpringApplicationRunListeners构造函数的时候赋值的。赋值之后不能修改
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 调用所有监听器的starting方法,通知各个监听器,spring开始启动了。要干事情的准备开干了
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			// 停止计时
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			// 调用监听器的started方法,告知上下文已经刷新,应用程序已经启动
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			// 调用自定义的run实现 这是在springboot上下文刷新程序启动完成之后
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

一来首先他就弄一个定时器出来并且按下开始按钮,开始计时 --> 检车当前的系统是否有显示器,并将其设置为没有显示器也可以启动 --> 通过SpringFactoriesLoader获取所有的自定义监听器 --> 通知所有的监听器,程序正在启动中。

到后面就是大戏了。

其实这里说到的系统启动监听器,初始化器的扩展,这是思路挺值得我们开发中学习的,定义一个接口,定义需要的方法,获取所有的实现类,并且创建其实例,然后在某个节点去调用其方法。将需要的参数进行传递过去,扩展性很好。

一个相信努力就会有结果的程序员,以兴趣驱动技术!         ------ CoderOu

猜你喜欢

转载自blog.csdn.net/qq_42154259/article/details/107549932