Spring Boot学习(五):Spring Boot启动类及其原理(解析run方法)

前言

上一篇博客,大致讲解了@SpringBootApplication的原理,那么在SpringBoot的启动类中就剩下一个重点了,那就是SpringApplication的run()方法,接下来,我会通过源码来对run方法进行一定的解析

public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

Spring Boot的run()方法解析

启动类调用的是以下这个run方法,可以看到他也是返回了一个run方法的结果

	/**一个静态方法,根据指定的来源和默认配置用于启动SpringApplication
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified source using default settings.
	 * @param primarySource the primary source to load
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return the running {@link ApplicationContext} 返回一个运行的ApplicationContext
	 */
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}

我们继续深入,发现它还是返回一个run方法的结果,但这里和上面有些不一样的了,它是先构造了一个参数为primarySources的SpringApplication对象,再调用run方法

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}


下面就是我们今天的主角了,还是一个run方法(第n个run方法,大家可以思考下为什么要分这么多个run方法?)。接下来让我们在源码中分析下今天的主角

/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 *运行Spring应用程序,创建并刷新一个新的ApplicationContext, args应用程序参数(通常从Java主方法传递),返回一个运行中的
	 *ApplicationContext,ConfigurableApplicationContext继承于ApplicationContext,是它的子接口
	 */
	public ConfigurableApplicationContext run(String... args) {
		//记录程序运行时间,StopWatch这个类通常用于验证某个的性能验证,是非线程安全的
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		//创建一个ConfigurableApplicationContext 对象,除了继承ApplicationContext接口中的应用程序上下文客户端方法之外,			还提供配置应用程序上下文的工具。
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//设置默认属性
		configureHeadlessProperty();
		//获取并启动监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			//ApplicationArguments 是一个提供用于运行SpringApplication 参数的类
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
       			 //构造应用上下文环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			//处理需要忽略的Bean,将需要忽略的bean放到spring.beaninfo.ignore属性中
			configureIgnoreBeanInfo(environment);
			打印banner,就是启动时候那个spring boot标识
			Banner printedBanner = printBanner(environment);
			///创建应用上下文
			context = createApplicationContext();
			//实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//准备应用上下文,进行一些注册加载的操作
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			//刷新应用上下文
			refreshContext(context);
			//在上下文刷新后调用的一个方法,查看源码,发现是一个空方法,应该是优化了
			afterRefresh(context, applicationArguments);
			//停止stopWatch
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			//ApplicationContext已经刷新,应用程序已经启动,但ApplicationRunners还没有被调用,用于发布信息
			listeners.started(context);
			//运行回调
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		//返回ApplicationContext
		return context;
	}

以上就是run()方法的大致流程。

具体实现,大家可以继续对代码进行深入阅读

你可能感兴趣的:(springboot,java,spring,boot,spring)