1.web容器
在以前的web应用中,我们知道java web应用程序包含servlet、jsp、css等资源组成,并在web.xml中添加应用配置,然后按照规范打包成一定的目录结构放入web容器中,web容器按照约定读去应用资源并启动服务。
但是SpringMVC支持可以直接打包部署启动,这是为何?
2.spi
Servlet 3.0引进spi技术,由测试项目无web.xml启动springmvc原理知道,容器启动后会读取应用路径META-INF/services中配置的ServletContainerInitializer实现类,并实例化这些实现类,又Context容器依次调用这些实现类的onstartup方法。
ServletContainerInitializer 类还支持HandlesTypes注解,该注解的参数会被读取当作onstartup的入参。
3.spring中的spi
spring在包org.springframework.web中定义了继承自ServletContainerInitializer的SpringServletContainerInitializer
@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {
SpringServletContainerInitializer的注解中声明了WebApplicationInitializer.class 类,那么WebApplicationInitializer.class 将作为onstartup方法入参。
onstartup中会调用WebApplicationInitializer实例的onstartup:
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
...
while(var4.hasNext()) {
WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
initializer.onStartup(servletContext);
}
...
那么最终,Spring的初始化将在WebApplicationInitializer的实现类中完成。WebApplicationInitializer实现类包含:
AbstractAnnotationConfigDispatcherServletInitializer
AbstractDispatcherServletInitializer
等。。。
另外还有SpringBootServletInitializer,可想而知springboot也支持非jar方式启动。搜索后果然发现该类用于支持war打包,参考:https://www.jianshu.com/p/aacbfbcf0cd7
在springboot自动装配中,可以看到类似spi技术的应用:通过META-INFO下的spring.factories文件配置服务类,ClassLoader加载文件中的服务类并加入spring容器中加以使用。