King's Studio

Spring Boot嵌入式Servlet容器启动原理

字数统计: 672阅读时长: 3 min
2019/04/21 Share

嵌入式Servlet容器启动原理

前面我们总结了Spring Boot中嵌入式Servlet容器自动配置原理,也提到了Spring Boot2.0版本中使用ServletWebServerFactoryConfiguration替换了EmbeddedServletContainerAutoConfiguration,那么什么时候创建嵌入式的Servlet容器工厂以及什么时候获取嵌入式的Servlet容器并启动Tomcat呢?我们进入到ServletWebServerFactoryConfiguration中查看。

获取嵌入式的Servlet容器从Spring Boot应用启动运行run()方法开始

以Tomcat为例,在new TomcatServletWebServerFactory()处打断点,以Debug方式运行。

Tomcat

我们发现第一步是从执行SpringBootRestfulcrudApplication的run()方法开始的。

SpringBootApplication

Spring Boot刷新IOC容器

Spring Boot刷新IOC容器,创建IOC容器对象,并且初始化容器,创建容器中每一个组件。

刷新

并进行判断,如果是web应用就创建AnnotationConfigServletWebServerApplicationContext,否则就创建默认的AnnotationConfigApplicationContext。此处Spring Boot2.0中也进行了更新,将原来的AnnotationConfigEmbeddedWebApplicationContext替换为AnnotationConfigServletWebServerApplicationContext。

判断

刷新刚创建好的IOC容器

调用refresh()方法刷新刚刚创建好的IOC容器。

refresh

web的IOC容器重写onRefresh()方法

1
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@Override
public void refresh() throws BeansException, IllegalStateException {
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()方法
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

web的IOC容器会创建嵌入式的Servlet容器

上一步会调用此处的createWebServer()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
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();
}

获取嵌入式的Servlet容器工厂

从IOC容器中获取ServletWebServerFactory组件,然后TomcatServletWebServerFactory创建对象,触发上一篇我们讲到的后置处理器,获取所有的定制器来定制Servlet容器的相关配置。

1
ServletWebServerFactory factory = getWebServerFactory();

使用容器工厂获取嵌入式的Servlet容器

1
this.webServer = factory.getWebServer(getSelfInitializer());

嵌入式的Servlet容器创建对象并启动Servlet容器如Tomcat

先启动嵌入式的Servlet容器,再将IOC容器中剩下的没有创建的对象获取得到,IOC容器启动创建嵌入式的Servlet容器。

Tomcat启动

原文作者:金奇

原文链接:https://www.rossontheway.com/2019/04/21/SpringBoot嵌入式Servlet容器启动原理/

发表日期:April 21st 2019, 12:00:00 am

更新日期:April 21st 2019, 4:44:52 pm

版权声明:本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可,除特别声明外,转载请注明出处!

CATALOG
  1. 1. 嵌入式Servlet容器启动原理
    1. 1.1. 获取嵌入式的Servlet容器从Spring Boot应用启动运行run()方法开始
    2. 1.2. Spring Boot刷新IOC容器
    3. 1.3. 刷新刚创建好的IOC容器
    4. 1.4. web的IOC容器重写onRefresh()方法
    5. 1.5. web的IOC容器会创建嵌入式的Servlet容器
    6. 1.6. 获取嵌入式的Servlet容器工厂
    7. 1.7. 使用容器工厂获取嵌入式的Servlet容器
    8. 1.8. 嵌入式的Servlet容器创建对象并启动Servlet容器如Tomcat