文档章节

SpringBoot:深入探索内嵌tomcat启动流程

wiitht
 wiitht
发布于 2017/08/16 16:23
字数 408
阅读 269
收藏 0

1.SpringBoot启动过程中所涉及的类:

springApplication -> run
stopwatch
AnnotationConfigApplicationContext: register, refresh  ->
AbstractApplicationContext -> refresh
AnnotationConfigEmbeddedWebApplicationContext
XmlBeanDefinitionReader
RepositoryConfigurationDelegate 
ClassPathMapperScanner
ConfigurationClassPostProcessor
GenericScope
AutowiredAnnotationBeanPostProcessor
TomcatEmbeddedServletContainer
StandardService
StandardEngine
WebApplicationContext
ContextLoader
ServletRegistrationBean
FilterRegistrationBean
RequestMappingHandlerMapping
EndpointHandlerMapping
SimpleUrlHandlerMapping
RequestMappingHandlerAdapter
ExceptionHandlerExceptionResolver
arterDeprecationWarningAutoConfiguration
URLConfigurationSource
AnnotationMBeanExporter
DefaultLifecycleProcessor
DocumentationPluginsBootstrapper
ApiListingReferenceScanner
CachingOperationNameGenerator
TomcatEmbeddedServletContainer
Application

2.初步分析SpringBoot启动过程

先看看在SpringApplication.run方法做了什么:

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.started();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			analyzers = new FailureAnalyzers(context);
			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);
		}
	}

其中refreshContext内部执行了refresh方法

protected void refresh(ApplicationContext applicationContext) {
		Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
		((AbstractApplicationContext) applicationContext).refresh();
	}

这个方法会刷新整个应用需要启动的东西,具体的在AbstractApplicationContext中refresh方法内部可以看到所有要启动加载的东西:

 public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if(this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

在这个过程中会加载相应的xml,启动注册要加载的bean,启动tomcat等等

tomcat启动的过程会异步启动一个守护监听的scoket线程,这个线程通过NIOChannel包装;当第一次收到请求的时候会初始化相关的scoketWrapper数据,并在调用的过程中将socket的数据以http协议的方式转化成HttpRequest对象,并且在过程中会通过wrapper找到相应的dispacthservelt然后调用filter, 具体的controller.

 

 

 

© 著作权归作者所有

共有 人打赏支持
wiitht
粉丝 3
博文 158
码字总数 113941
作品 0
深圳
架构师
私信 提问
深入源码大白话理解SpringBoot 究竟是如何跑起来的?

前言背景 SprintBoot是当今最流行的项目构建框架,但是大多数人会像我一样开始只会用,怎么搭建项目,怎么让项目跑起来,但是有没有真正去研究一个简简单单的Hello World程序是如何运行起来的...

懿宁19931210
01/09
0
0
springboot的内存占用

公司现在的项目都使用springboot,上线之后发现内存都最少用了100多M,我试了一个什么都没有的项目,只有一个启动类的springboot项目,启动起来也需要100多M,我使用jvisualvm查看,堆内存使...

迷途的码农
2017/10/08
502
3
SpringBoot | 第一章:第一个SpringBoot应用

SpringBoot | 第一章:第一个SpringBoot应用 springboot简单介绍 概述 随着动态语言的流行(Ruby、Groovy、Scala、Node.js),Java的开发显得格外的笨重:繁多的配置、低下的开发效率、复杂的...

oKong
2018/07/15
0
0
【SpringBoot专题】快速体验

前言 在Spring 4推出来之前,我们的编码是存在一些问题,比如:大量的xml配置存在项目中,配置相当繁琐;整合第三方框架非常麻烦;开发效率和部署效率不高等问题。正是因为这些问题,Spring开...

张丰哲
2018/08/05
0
0
SpringBoot|第一章:第一个SpringBoot 应用

springboot简单介绍 概述 随着动态语言的流行(Ruby、Groovy、Scala、Node.js),Java的开发显得格外的笨重:繁多的配置、低下的开发效率、复杂的部署流程以及第三方技术集成难度大。 在上述...

Java架构解析
2018/08/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

深度学习为图片人物换装【python代码教程】

在观看本文之前,请答应我要善良。昨天预告了下,发现很多同学对这个模型都表示出兴趣,甚至有好多同学后台发来照片让我帮他们脱裤子。授人以鱼不如授人以渔,请这些同学好自为之~ 01效果演示...

阿里云官方博客
22分钟前
1
0
centos7安装RabbitMQ详细过程

由于RabbitMQ是基于Erlang语言开发,所以在安装RabbitMQ之前,需要先安装Erlang 1、环境: centos 7.1 内核版本3.10.0-229.el7.x86_64 Erlang 19.0.4版本 RabbitMQ 3.6.14版本 2、在线安装E...

秋至丶枫以落
53分钟前
1
0
6个使用KeePassX保护密码的技巧

虽然安全是个深奥的主题,但是你可以遵循几个简单的日常习惯来减小攻击面。本文将解释确保密码信息安全的重要性,并给出如何充分利用KeePassX的建议。 日益互联的数字世界使安全成为一个重要...

Linux就该这么学
54分钟前
1
0
UnsatisfiedLinkError sawindbg.dll

方法:搜索sawindbg.dll,然后将文件报错的目录下

洛水
今天
5
0
说说不知道的Golang中参数传递

本文由云+社区发表 导言 几乎每一个C++开发人员,都被面试过有关于函数参数是值传递还是引用传递的问题,其实不止于C++,任何一个语言中,我们都需要关心函数在参数传递时的行为。在golang中...

腾讯云加社区
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部