每日一课 | Spring Boot 启动原理-02

05.
Spring Boot启动原理-02
大家好,我营长,上期给大家分享——Spring Boot 启动原理-01
本期分享内容:Spring Boot 启动原理-02
本期小C邀请的是李熠老师(某大型互联网公司系统架构师)为我们分享《Spring Cloud快速入门》专栏。
Spring Cloud
Spring Boot启动原理
源码解析
我们知道,启动类先调用了 SpringApplication 的静态方法 run,跟踪进去后发现,它会先实例化 SpringApplication,然后调用 run 方法。
/*** Static helper that can be used to run a {@link SpringApplication} from the* specified sources using default settings and user supplied arguments.* @param primarySources the primary sources to load* @param args the application arguments (usually passed from a Java main method)* @return the running {@link ApplicationContext}*/public static ConfigurableApplicationContext run(Class>[] primarySources,String[] args) {return new SpringApplication(primarySources).run(args);}
所以,要分析它的启动源码,首先要分析 SpringApplicaiton 的构造过程。
SpringApplication 构造器
在 SpringApplication 构造函数内部,他会初始化一些信息:
public SpringApplication(Class>... primarySources) {this(null, primarySources);}public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));this.webApplicationType = WebApplicationType.deduceFromClasspath();setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();}
通过上述代码,我们分析到 SpringApplication 实例化时有以下几个步骤:
将所有 sources 加入到全局 sources 中,目前只有一个 Application。
判断是否为 Web 程序(javax.servlet.Servlet、org.springframework.web.context.ConfigurableWebApplicationContext 这两个类必须存在于类加载器中)。
判断过程可以参看以下源码:
static WebApplicationType deduceFromClasspath() {if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {return WebApplicationType.REACTIVE;}for (String className : SERVLET_INDICATOR_CLASSES) {if (!ClassUtils.isPresent(className, null)) {return WebApplicationType.NONE;}}return WebApplicationType.SERVLET;}
设置应用程序初始化器 ApplicationContextInitializer,做一些初始化的工作。
设置应用程序事件监听器 ApplicationListener。
找出启动类,设置到 mainApplicationClass 中。
SpringApplication 的执行流程
SpringApplication 构造完成后,就会调用 run 方法,这时才真正的开始应用程序的执行。
先来看看源码:
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection exceptionReporters = new ArrayList<>();configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);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);}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);}return context;}
通过上述源码,将执行流程分解如下:
初始化 StopWatch,调用其 start 方法开始计时。
调用 configureHeadlessProperty 设置系统属性 java.awt.headless,这里设置为 true,表示运行在服务器端,在没有显示器和鼠标键盘的模式下工作,模拟输入输出设备功能。
遍历 SpringApplicationRunListeners 并调用 starting 方法。
创建一个 DefaultApplicationArguments 对象,它持有 args 参数,就是 main 函数传进来的参数调用 prepareEnvironment 方法。
打印 banner。
创建 Spring Boot 上下文。
初始化 FailureAnalyzers。
调用 prepareContext。
调用 AbstractApplicationContext 的 refresh 方法,并注册钩子。
在容器完成刷新后,依次调用注册的 Runners。
调用 SpringApplicationRunListeners 的 finished 方法。
启动完成并停止计时。
初始化过程中出现异常时调用 handleRunFailure 进行处理,然后抛出 IllegalStateException 异常。
今日内容有get吗,欢迎各位留言讨论!
下期预告:初识Spring Cloud
以上专栏均来自CSDN GitChat专栏《Spring Cloud快速入门》,作者李熠,专栏详情可识别下方二维码查看哦!
了解更多详情
可识别下方二维码

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
