SpringBoot中内置Servlet容器原理

发布时间 2023-09-21 21:32:36作者: LycCj

本篇博客会梳理一下SpringBoot内置Servlet容器的原理:

原理其实跟SpringBoot中的内置Tomcat的启动原理差不多,我们从整个源码进行梳理一下。

我们会发现当我们从Spring,SpringMVC演化到SpringBoot后发现采用SpringBoot后不需要配置Tomcat服务器了,这是什么原因呐,我们启动整个SpringBoot容器后,如果我们不配置相关的端口的参数,会发现整个项目会泡在本地电脑的8080端口,大家有没有想过其中的真实的原因,其实SpringBoot帮我们做了很多事,屏蔽掉了很多底层的细节点,因此我们需要不断的 "抽丝" 揭秘一下SpringBoot到底帮我们做了哪些事情,我们先来看下启动整个SpringBoot项目的主启动类:

@SpringBootApplication
public class CustomApplication {
    public static void main(String[] args) {
        SpringApplication.run(CustomApplication.class,args);
    }
}

注意我们在使用springBoot时候会使用到相应的maven依赖,先来查看一下对应的maven依赖:

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

当依赖Spring-boot-starter-web时候会在SpringBoot中添加 ServletWebSeverFactoryAutoConfiguraion.的servlet容器的自动配置类:

image-20230921204449937

  • 该自动给配置类通过@Import导入了可用(通过ConditionOnClass判断决定使用哪一个)web容器工厂(默认Tomcat)

image-20230921204946678

爆红说明暂不支持该服务器的servlet容器

接下来来看下启动流程分析:

image-20230921205421412

当我们在使用启动run方法的时候会调用一个叫createApplicationContext方法,该方法会返回一个容器叫作AnnotationConfigServletWebServerApplicationContext的容器。

之后会调用容器的refresh方法,帮我们去加载IOC容器:

其实是调用的refreshContext方法:

image-20230921210024178

image-20230921205941059

其中refresh中有个方法叫作invokeBeanFactoryPostProcessors()方法他会解析所有@Bean标注的bean,将这些bean标注进来:

image-20230921210513419

接下来他会调用一个叫作onRefresh的方法:

注意此时我们是在AbstractApplicationContext中获取的方法我们会发现该方法什么都没有实现,那么对于成熟的Spring框架肯定不会写一些无用的方法,那么很显然该方法是由AbstractApplicationContext子类来完成实现的:

其中有一个叫ServletWebServerApplicationContext的子类:

image-20230921210824558

然后跟进方法:

image-20230921211047297

注意其中有一个被try...catch....块包裹的函数叫作createWebServer()函数:

image-20230921211153121

然后其中有一个方法叫作getWebServerFactory的方法获取我们所配置的ServletWebServerFactory,还记得我们在invokeBeanFactoryPostProcessors中的将TomcatServletWebServerFactory已经配置进来了:

image-20230921211653250

然后拿到对应的TomcatServletWebServerFactory后会有一个getWebServer方法:

image-20230921211921017

再次点进去就会发现最核心的代码:

image-20230921211958056

然后我们不断点进去getTomcatWebServer方法:Tomcat被启动:

image-20230921212116470

然后挂起等待请求:startDaemonAwaitThread:

image-20230921212310001

完结:

​ 这就是SpringBoot中内置servlet容器的原理!!!