SpringBoot关于嵌入式servlet容器与外部servlet容器的启动原理的总结(基于Tomcat)
转载
具体参考:尚硅谷SpringBoot顶尖教程(springboot之idea版spring boot)
嵌入式servlet容器
-
SpringBoot应用启动,执行run方法
public static void main(String[] args) { SpringApplication.run(xxxApplication.class, args); }
-
执行 refreshContext(context) SpringBoot刷新IOC容器 : 创建IOC容器对象,并初始化容器,创建容器中的每一个组件。如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext,否则创建:AnnotationConfigApplicationContext
-
refresh(context);刷新刚才创建好的ioc容器;
-
onRefresh() web的ioc容器重写了onRefresh方法
-
web的ioc容器会创建嵌入式的Servlet容器;createEmbeddedServletContainer()
-
获取嵌入式的Servlet容器工厂
EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
从ioc容器中获取EmbeddedServletContainerFactory 组件:TomcatEmbeddedServletContainerFactory创建对象,后置处理器一看是这个对象,就获取所有的定制器来先定制Servlet容器的相关配置
-
使用容器工厂获取嵌入式的Servlet容器
this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer())
-
先启动嵌入式的Servlet容器,再将ioc容器中剩下没有创建出的对象获取出来(servlet, listener, filter)
总结:先创建ioc容器 —> IOC容器中注入servlet容器 —> 获取嵌入式的Servlet容器工厂 —> 使用这个工厂创建嵌入式的Servlet容器 —> 使用这个容器注入Servlet,listener,filter
注意:嵌入式Servlet容器:应用打成可执行的jar包
不支持JSP
外置的servlet容器
-
启动Tomcat
-
Spring的web模块里面有这个文件:org.springframework.web.SpringServletContainerInitializer
-
SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的类都传入到onStartup方法;为这些WebApplicationInitializer类型的类创建实例
-
每一个WebApplicationInitializer都调用自己的onStartup
-
相当于我们的SpringBootServletInitializer的类会被创建对象,并执行onStartup方法
//必须编写一个SpringBootServletInitializer的子类, 并调用configure方法 public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { //传入SpringBoot应用的主程序 return application.sources(xxxApplication.class); } }
-
SpringBootServletInitializer实例执行onStartup的时候会通过 createRootApplicationContext :创建容器
protected WebApplicationContext createRootApplicationContext( ServletContext servletContext) { //1、创建SpringApplicationBuilder SpringApplicationBuilder builder = createSpringApplicationBuilder(); //省略 //调用configure方法,子类重写了这个方法(见上),将SpringBoot的主程序类传入了进来 builder = configure(builder); //使用builder创建一个Spring应用 SpringApplication application = builder.build(); //省略 //启动Spring应用 return run(application); }
-
Spring的应用就启动并且创建IOC容器
public ConfigurableApplicationContext run(String... args) { //省略 //刷新IOC容器 refreshContext(context); //省略 }
总结:启动Tomcat服务器 —> 服务器启动SpringBoot应用 —> 启动IOC容器
注意:外置的Servlet容器:外面安装Tomcat—用war包的方式打包 —
此时的依赖:
<!--将嵌入式的tomcat指定为provided-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
对比总结
-
嵌入式servlet容器
-
打包方式:jar
-
启动顺序:先IOC,后Servlet
-
无需手动安装Tomcat
-
不支持JSP
-
Tomcat依赖不需要设置为
<scope>provided</scope>
-
-
外置的servlet容器
-
打包方式:war
-
启动顺序:先Servlet,后IOC
-
需要安装Tomcat
-
支持JSP
-
Tomcat依赖需要设置为
<scope>provided</scope>
-