源码解析:spring boot 创建内嵌Tomcat容器并启动
基于版本spring boot 2.1.5.RELEASE
spring boot 启动时会调用SpringApplication#run(String... args)
方法,一切都从这里开始。
整体流程
1. ApplicationContext创建
spring boot会调用org.springframework.boot.SpringApplication#createApplicationContext
方法,根据webApplicationType
值创建ApplicationContext
。
一般web环境都是创建AnnotationConfigServletWebServerApplicationContext
,也只有当前应用为网络应用时才会启动内嵌的 Servlet 容器。(Servlet 容器创建及启动的实现在ServletWebServerApplicationContext
中,而AnnotationConfigServletWebServerApplicationContext
继承了该类)。
2. 创建Servlet 容器
run
方法中,spring boot会通过refreshContext()
方法调用ApplicationContext
的refresh()
方法(该方法由ApplicationContext
实例的父类AbstractApplicationContext
提供实现,是模板方法的应用,里面定义了ApplicationContext
的启动流程)。
refresh()方法定义的流程
public void refresh() {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
... ...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
子类ServletWebServerApplicationContext
重写的onRefresh()
方法被调用。
这个方法里通过createWebServer()
创建了 Servlet
容器(默认为 Tomcat),并添加 IoC 容器中的 Servlet
、Filter
和 EventListener
至 Servlet
上下文。
3. 启动容器
子类ServletWebServerApplicationContext
重写的finishRefresh()
方法被调用。
这个方法里通过startWebServer()
调用WebServer#start
方法启动创建的容器。
createWebServer 方法
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer
以tomcat容器为例:
private void createWebServer() {
WebServer webServer = this.webServer;
// 获取被加载都ioc容器中的TomcatServletWebServerFactory
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
// 生成一个TomcatWebServer实例
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
spring boot在org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer
给tomcat设置了相关的配置。
其中org.apache.catalina.connector
的实例化给Tomcat引入了默认配置。
源码路径:
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer
Connector connector = new Connector(this.protocol);
Class<?> clazz = Class.forName(protocolHandlerClassName);
org.apache.coyote.http11.Http11NioProtocol
org.apache.coyote.AbstractProtocol
org.apache.coyote.AbstractProtocol#endpoint
默认配置保存在这个类中。
maxThreads: 用于接收和处理client端请求的最大线程数,默认200
acceptCount: tomcat 线程池所有线程忙碌时,等待队列的最长长度。默认100
connectionTimeout:每个http请求的读取超时时间。默认2000ms