Springboot 2启动内置Tomcat源码分析
以 Spring MVC 启动 Servlet 为例,其应用上下文为 ServletWebServerApplicationContext,继承了 GenericWebApplicationContext 的大部分方法,主要重写了 postProcessBeanFactory()、refresh()、onRefresh()、finishRefresh()、onClose() 方法。
启动流程
由 refresh() 可知,重写方法的执行顺序为:postProcessBeanFactory()、onRefresh()、finishRefresh()。
1、postProcessBeanFactory()
- 添加后置处理器 WebApplicationContextServletContextAwareProcessor
- 忽略自动装配以来接口 ServletContextAware
- 注册 web 应用的作用域
2、onRefresh()
- 调用父类的 onRefresh() 方法
- 创建 Web 服务器
Spring 容器中会加载 @Configuration 注解的配置类 ServletWebServerFactoryConfiguration,它会按条件注入不同的 web 服务器工厂类:Tomcat/Jetty/Undertow,默认条件下,可以注入 TomcatServletWebServerFactory, name 为 tomcatServletWebServerFactory。
onRefresh() 创建 Web 服务器时,首先从 BeanFactory 获取 ServletWebServerFactory 类型的 Bean,即上述的 TomcatServletWebServerFactory。利用这个工厂类的方法public WebServer getWebServer(ServletContextInitializer... initializers)
来创建 TomcatWebServer,这个方法主要就是为 TomcatWebServer 创建 Tomcat 实例。此外,注意其入参 ServletContextInitializer 是函数式接口,可以将其方法作为参数传入,初始化 TomcatWebServer 时,调用 Tomcat.start() 启动 Server,以异步的方式执行该函数接口的实现类,即执行 onStartup() 方法。
创建 Tomcat 实例,是和 Tomcat 启动相关的内容,也就是创建 Tomcat 相关的组件的过程,比如 Server、Service、Connector、Engine、Host、Context、Wrapper 、Lifecycle 等组件。
Tomcat 将在这一步完成初始化的工作,其生命周期状态变化为:NEW
->INITIALIZING
->INITIALIZED
,INITIALIZED
表示已经初始化的状态。
3、finishBeanFactoryInitialization(beanFactory)
从 BeanFactory 获取 name 为 requestMappingHandlerMapping 的 Bean,并初始化这个 Bean,过程中执行其实现的接口方法 InitializingBean.afterPropertiesSet(),该方法遍历所有可用的 Bean,找到 @Controller 或者 @RequestMapping 注解的类,利用反射技术,遍历出这些类的方法及其请求 URL 的映射关系进行缓存。
4、finishRefresh()
真正完成启动 Tomcat,其生命周期状态变化为:INITIALIZED
->STARTING_PREP
->STARTING
->STARTED
,即表示启动成功。
请求流程
Tomcat 接收请求
- 浏览器输入http://127.0.0.1:8080/test,地址127.0.0.1、端口号8080的 Endpoint 接收到请求,并将请求交给处理器 Processor 处理;
- 处理器将请求通过适配器 CoyoteAdapter,从缓存 Mapper 中找到路径映射,从而依次找到 Engine->Host->Context->Wrapper
- 先调用过滤器链 FilterChain,过滤之后,执行 Servlet
- 执行完毕,再将响应 Response 依次返回
DispatcherServlet
Tomcat 作为 Servlet 容器,负责监听 Socket 请求,并将请求映射、并转交给具体的 Servlet 进行处理。Spring MVC 中非常重要的,负责请求处理调度的类 DispatcherServlet,就是 Servlet 的一个实现,所以在 Spring MVC 应用中,是使用 DispatcherServlet 来处理请求的,其实现 Servlet 的继承关系如下图:
DispatcherServlet 获取到请求后的执行流程