前言
SpringBoot出现之前,使用Spring框架开发一个web应用并发布到Servlet容器,通常是下载安装一个Tomcat(或者其他),然后将应用打成war包,然后放到Tomcat的WebApp目录下, 然后启动Tomcat,访问应用。而有了SpringBoot之后,我们只需在main方法启动就可以访问应用了,这是因为SpringBoot为我们内置了Servlet容器,并在应用启动时,启动了Servlet容器。那么SpringBoot是如何帮我们内置的呢?
一、SpringBoot何处启动Servlet容器?
这里需要先了解一下(SpringBoot的启动流程),SpringBoot就是在执行
refreshContext(刷新web应用上下文)
的时候创建并启动Servlet容器的,这里的上下文对象是AnnotationConfigServletWebServerApplicationContext
,它间接继承了AbstractApplicationContext
,而refreshContext
内部调用了AbstractApplicationContext#refresh
方法,里面又调用了onRefresh
方法,而这个方法是AbstractApplicationContext
的受保护方法同时是一个空方法,AnnotationConfigServletWebServerApplicationContext
(实际是它的直接父类)就是重写了onRefresh
方法,完成对Servlet容器的创建并启动!
二、 获取ServletWebServerFactory
ServletWebServerFactory
是创建Servlet容器的工厂,这里需要先获取工厂对象,再根据工厂对象创建对象的Servlet容器,比如我们常见的Tomcat,Undertow,Jetty
等Servlet容器,它们对应不同的工厂对象。这里SpringBoot会根据我们所引入的具体依赖,为我们自动配置这几种工厂对象(了解SpringBoot的自动配置)。它的配置类是ServletWebServerFactoryAutoConfiguration
里面通过@Import,导入了Tomcat,Undertow,Jetty
等配置类,并在解析配置类后,将它们的bean定义信息保持在Spring容器中。
另外还导入了一个类
BeanPostProcessorsRegistrar
它是其内部类,实现了ImportBeanDefinitionRegistrar
,目的是用来注册WebServerFactoryCustomizerBeanPostProcessor
的bean定义信息,WebServerFactoryCustomizerBeanPostProcessor
作用从它的类名可以看出,是在ServletWebServerFactory
这个bean初始化的时候对它进行自定义增强的,主要是获取配置文件的值(ServerProperties
对应的值,比如常见的server.port
、server.servlet.contextPath
),设置到ServletWebServerFactory
对象,以便这个工厂创建容器对象时使用
调用getWebServerFactory方法,从Spring容器中获取
ServletWebServerFactory
这个bean,获取bean时Spring容器中有且仅有一个ServletWebServerFactory
,这就是自动配置时,根据条件(引入的依赖等)判断实例化ServletWebServerFactory
对象,默认是创建TomcatServletWebServerFactory
(spring-boot-starter-web.jar中默认依赖tomcat容器),如果排除这个依赖引入其他依赖就创建其他ServletWebServerFactory
完成ServletWebServerFactory的实例化后,在初始化时执行WebServerFactoryCustomizerBeanPostProcessor#postProcessBeforeInitialization方法,对其进行扩展处理
调用
getWebServerFactoryCustomizerBeans
方法,获取相关的WebServerFactoryCustomizer
对象将其实例化,并绑定了ServerProperties(配置文件中的配置信息)。WebServerFactoryCustomizer
配置在ServletWebServerFactoryAutoConfiguration
中定义了(当然除了这2个还有其他的)
获取到
WebServerFactoryCustomizer
对象,调用它们的customize
方法,这里看下ServletWebServerFactoryCustomizer
和TomcatServletWebServerFactoryCustomizer
的customize方法,其实就是获取相关配置信息,设置到ServletWebServerFactory
工厂对象中。到这里工厂对象差不多就初始化完毕。
三、获取Servlet容器并启动
上面工厂对象(默认
TomcatServletWebServerFactory
)创建好了,通过工厂对象调用getWebServer方法,根据配置文件中的配置值创建并启动Servlet容器。这里Servlet容器的创建和启动过程细节就不讲了(我没研究过[苦笑]),贴几张图吧,哈哈哈
总结
以上就是对SpringBoot如何内置Servlet容器简单分析,有误之处还望指出,谢谢!