ServletContainerInitializer
SpringServletContainerInitializer
spring boot项目如何调用?
存在于spring-web项目的META-INF/services/javax.servlet.ServletContainerInitializer文件中
实现了ServletContainerInitializer,调用所有WebApplicationInitializer接口实现的onStartup方法,完成启动容器时初始化配置
@HandlesTypes会自动扫描项目中所有的WebApplicationInitializer.class的实现类,并将其全部添加到Set,分别调用其onStartup方法
- spring mvc中有WebApplicationInitializer的实现类AbstractDispatcherServletInitializer,该类注册了DispatcherServlet
- spring boot中有WebApplicationInitializer的实现类SpringBootServletInitializer,该类添加了ContextLoaderListener,创建并初始化了RootApplicationContext
spring-web项目如何调用?
SPI机制
在web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等,servlet规范中通过ServletContainerInitializer实现此功能。
每个框架要使用ServletContainerInitializer就必须在对应的jar包的META-INF/services目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。
一般伴随着ServletContainerInitializer一起使用的还有HandlesTypes注解,通过HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializer的onStartup方法作为参数传入。
加载过程:Tomcat容器的ServletContainerInitializer机制的实现,主要交由Context容器和ContextConfig监听器共同实现
ContextConfig监听器负责在容器启动时读取每个web应用的WEB-INF/lib目录下包含的jar包的META-INF/services/javax.servlet.ServletContainerInitializer,以及web根目录下的META-INF/services/javax.servlet.ServletContainerInitializer(即直接在src下建立的META-INF/services/javax.servlet.ServletContainerInitializer),通过反射完成这些ServletContainerInitializer的实例化,然后再设置到Context容器中。
首先通过ContextConfig监听器遍历每个jar包或web根目录的META-INF/services/javax.servlet.ServletContainerInitializer文件,根据读到的类路径实例化每个ServletContainerInitializer。
然后再分别将实例化好的ServletContainerInitializer设置进Context容器中。
最后Context容器启动时分别调用所有ServletContainerInitializer对象的onStartup方法。