servlet3.0的8.2.4 Shared libraries / runtimes pluggability中的规则:
1.服务器启动(web应用启动)会创建当前web应用里面每一个jar包里面ServletContainerInitializer实例
2.ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,有一个javax.servlet.ServletContainerInitializer的文件,内容是ServletContainerInitializer实现类的全类名
3.可以使用 @HandleTypes注解,在应用启动时加载需要的类
流程:
1.启动Tomcat
2.
org\springframework\spring-web\5.1.9.RELEASE\spring-web-5.1.9.RELEASE.jar\META-INF\services\javax.servlet.ServletContainerInitializer
Spring的web模块中有这个文件:org.springframework.web.SpringServletContainerInitializer
3.SpringServletContainerInitializer将@HandleTypes({WebApplicationInitializer.class})标注的所有类型的类都传入到onStartup方法的Set<Class<?>>中,为WebApplicationInitializer类型的类创建实例
4.每一个WebApplicationInitializer都调用自己的onStartup方法启动
5.SpringBootServletInitializer类会创建对象并执行onStartup方法启动
6.SpringBootServletInitializer执行onStartup方法会调用createRootApplicationContext创建容器
protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
// 创建SpringApplicationBuilder构建器
SpringApplicationBuilder builder = this.createSpringApplicationBuilder();
builder.main(this.getClass());
ApplicationContext parent = this.getExistingRootWebApplicationContext(servletContext);
if (parent != null) {
this.logger.info("Root context already created (using as parent).");
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, (Object)null);
builder.initializers(new ApplicationContextInitializer[]{new ParentContextApplicationContextInitializer(parent)});
}
builder.initializers(new ApplicationContextInitializer[]{new ServletContextApplicationContextInitializer(servletContext)});
builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);
// 调用configure方法,子类重写该方法,将SpringBoot的主程序类传入进来
builder = this.configure(builder);
builder.listeners(new ApplicationListener[]{new SpringBootServletInitializer.WebEnvironmentPropertySourceInitializer(servletContext)});
// 使用builder创建一个Spring应用
SpringApplication application = builder.build();
if (application.getAllSources().isEmpty() && AnnotationUtils.findAnnotation(this.getClass(), Configuration.class) != null) {
application.addPrimarySources(Collections.singleton(this.getClass()));
}
Assert.state(!application.getAllSources().isEmpty(), "No SpringApplication sources have been defined. Either override the configure method or add an @Configuration annotation");
if (this.registerErrorPageFilter) {
application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));
}
// 启动Spring应用
return this.run(application);
}
7.Spring就启动成功,并且创建IOC容器
protected WebApplicationContext run(SpringApplication application) {
return (WebApplicationContext)application.run(new String[0]);
}
先启动Servlet容器,再启动SpringBoot应用