SpringBoot启动流程简析(二)
来源:互联网 发布:做淘宝直播怎么找商家 编辑:程序博客网 时间:2024/06/03 17:25
在这篇文章中,我们接着上一篇的内容接着分析。
public ConfigurableApplicationContext run(String... args) { //启动应用的检测 StopWatch stopWatch = new StopWatch(); stopWatch.start(); //SpringBoot的上下文 ConfigurableApplicationContext context = null; //失败分析报告 FailureAnalyzers analyzers = null; configureHeadlessProperty(); //SpringBoot的runlistener SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { //参数解析 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); //配置环境变量 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); //输出Banner信息 Banner printedBanner = printBanner(environment); //创建应用上下文 context = createApplicationContext(); analyzers = new FailureAnalyzers(context); //refresh上下文之前的准备 prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
SpringApplication中的run方法的内容如上所示,上面就是整个SpringBoot应用启动的主要调用方法,run方法中的参数即是我们的应用参数。下面我们来简单的分析一下这个启动过程。
StopWatch主要是监控启动过程,统计启动时间,检测应用是否已经启动或者停止。
SpringApplicationRunListeners listeners = getRunListeners(args);private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args));}
通过在上一篇文章中的问题,对于getSpringFactoriesInstances这个方法你应该不陌生来吧。这里也是从META-INF/spring.factories中获取类型为org.springframework.boot.SpringApplicationRunListener的配置值,这个默认的配置值为:org.springframework.boot.context.event.EventPublishingRunListener。我们进入到EventPublishingRunListener这个类看一下它的构造函数
public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; //创建一个SimpleApplicationEventMulticaster this.initialMulticaster = new SimpleApplicationEventMulticaster(); //把之前在SpringApplication中获取到的listener循环放入到SimpleApplicationEventMulticaster中 for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } }
通过上面的分析,我们可以看到EventPublishingRunListener把SpringApplication中的监听器,都放到了SimpleApplicationEventMulticaster中,进行了统一的管理。listeners.starting();启动事件监听,这里以后我们单独开章节详细说明.
//创建应用参数解析器 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args);
我们看一下DefaultApplicationArguments的构造函数的内容:
public DefaultApplicationArguments(String[] args) { //首先判断不能为null,这里大家可以想一下可变参数如果不传值的话看看是什么内容 Assert.notNull(args, "Args must not be null"); //调用Source对应用参数进行解析 this.source = new Source(args); this.args = args; }
Source(String[] args) {//调用父类的构造函数 Source的继承关系如下图所示 super(args);}public SimpleCommandLinePropertySource(String... args) { //对应参数进行解析的工作 super(new SimpleCommandLineArgsParser().parse(args));}
大家在配置应用参数的时候,是这样这样配置的 - -key=value,为什么要以- -开头呢?在SimpleCommandLineArgsParser的parse方法中你会找到答案。并且Source这个类还继承类PropertySource这个类。
//准备环境变量ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments); private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { //获取环境变量 ConfigurableEnvironment environment = getOrCreateEnvironment(); //将应用参数放入到环境变量持有对象中 configureEnvironment(environment, applicationArguments.getSourceArgs()); //监听器监听环境变量对象的变化 listeners.environmentPrepared(environment); //如果非web环境,则转换为StandardEnvironment对象 if (!this.webEnvironment) { environment = new EnvironmentConverter(getClassLoader()) .convertToStandardEnvironmentIfNecessary(environment); } return environment;}
private ConfigurableEnvironment getOrCreateEnvironment() { //如果已经创建过存放环境变量的对象了,则直接返回 if (this.environment != null) { return this.environment; } //如果是web环境则创建StandardServletEnvironment对象 if (this.webEnvironment) { return new StandardServletEnvironment(); } //非web环境,创建StandardEnvironment return new StandardEnvironment(); }
StandardServletEnvironment的UML图如下所示,StandardServletEnvironment集成了系统变量、环境变量、配置属性信息等内容。这些内容我们以后单开一个篇章来说一下。
//这句话是输出SpringBoot的Banner信息,可以从指定的位置加载信息,可以输出为文字形式,也可以输出为图片形式,如我们常见的SpringBoot的logo就是在这里输出的Banner printedBanner = printBanner(environment);
Banner的UML类图如下所示:
我们最常见的SpringBoot的logo“图像”就在SpringBootBanner这个类中定义的,这个也是SpringBoot默认的Banner类。
//创建SpringBoot的应用上下文context = createApplicationContext();protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { //DEFAULT_WEB_CONTEXT_CLASS = org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext /// DEFAULT_CONTEXT_CLASS = org.springframework.context.annotation.AnnotationConfigApplicationContext contextClass = Class.forName(this.webEnvironment ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS); } } return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);}
因为我们是web开发环境,所以这里我们的web上下文是AnnotationConfigEmbeddedWebApplicationContext这个对象,一定要记住这个类,要仔细的看看它的UML类图。
- SpringBoot启动流程简析(二)
- SpringBoot启动流程简析(一)
- SpringBoot启动流程简析(三)
- SpringBoot启动流程简析(四)
- SpringBoot-启动流程分析
- SpringBoot应用启动流程
- SpringBoot启动流程解析
- SpringBoot启动流程解析
- SpringBoot应用启动流程
- SpringBoot启动流程详解(搬运)
- 深入浅出:linux的启动流程刨析(二)
- SpringBoot开发入门(二)在Tomcat中启动
- 97. SpringBoot-启动流程分析第一篇
- 【Spring Boot】SpringBoot-启动流程分析
- SpringBoot——run启动流程
- Activity的启动流程(二)
- Activity的启动流程(二)
- Linux基础(二):计算机启动流程
- testtrymd
- markdown编辑器语法
- ubuntu16.04安装opencv找不到cv2.so问题解决
- java关于多线程相关问题
- 2017/12/19 bootstrap登陆界面样式
- SpringBoot启动流程简析(二)
- [SpringMVC 源码] SpringMVC 中 HTTP 请求与响应原理
- Spring Security 入门教程 -01- Hello World
- 渐行渐远
- UE4中制作高大上的相机动画
- JAVA设计模式之单例模式
- Androi_SwipeRefreshLayout上拉刷新、AVLoadingIndicatorView加载动画
- 翻译:macOS10.12.2 local_privilage_Escalation
- 死磕红皮书(在HTML中使用Javascript)