servlet容器如何找到WebApplicationInitializer实现

Ant*_*hik 7 java spring servlets spring-mvc servlet-3.0

Spring WebApplicationInitializer提供了一种在Servlet 3.0+兼容的servlet容器中配置Spring DispatcherServlet和ContextLoaderListener的编程方法.但它是如何工作的?servlet容器如何找到WebApplicationInitializer实现,它是否真的从类路径加载所有类?

Tom*_*ian 10

我假设您了解java SPI以及用于加载实现的java.util.ServiceLoader实用程序类的方式.否则请阅读.

但简而言之,这个答案只是理解:如果有一个SPI,javax.servlet.ServletContainerInitializer那么提供者应该实现它,并且必须在库jar文件的META-INF/services/javax.servlet.ServletContainerInitializer文件中声明实现- Spring是这样的提供者并在spring-web*.jar jar文件中声明并且有一个条目org.springframework.web.SpringServletContainerInitializer 然后ServletContainerInitializer的服务加载器可以加载实现.此加载特定于ServletContainer实现

我将解释这个特定于tomcat7 + ServletContainer.

Tomcat有LifecycleListeners那些会聆听生命周期事件,如启动,停止等, org.apache.catalina.startup.ContextConfig就是这样将用于配置该的属性ServletContext的启动事件侦听器的ServletContext,以及相关的定义的servlet.

因此,当tomcat ServletContext为web应用程序初始化时,它将生成这样的事件,该事件将通知ContextConfig甚至是监听方法.然后它将触发自己的processServletContainerInitializers方法,该方法扫描JAR以获取ServletContainerInitializer实现.它通过将此职责委托给WebappServiceLoader(Java的JAR ServiceLoader的变体)来实现这一点,WebappServiceLoader实际上负责从WEB-INF/lib jar 加载ServletContainerInitializer实现.

因此,作为结论,控制流程将是这样的.

  1. Tomcat初始化ServletContext

  2. ContextConfig 通过此上下文启动事件通知

  3. 服务加载委托给 WebappServiceLoader<ServletContainerInitializer>

  4. WebappServiceLoader在WEB-INF/lib jar中扫描文件META-INF/services/javax.servlet.ServletContainerInitializer以便加载实现

  5. 一旦加载返回到步骤3,ContextConfig将调用实现的(此处SpringServletContainerInitializer) onStartup方法,该方法将执行其余的操作.

HTH!


mar*_*bog 2

来自文档:

此 SPI 的实现将由
SpringServletContainerInitializer 自动检测,它本身由任何 Servlet 3.0 容器自动引导。请参阅 SpringServletContainerInitializer 或有关此引导机制的详细信息。

和:

运作机制

SpringServletContainer初始化器


假定 spring-web 模块 JAR 存在于类路径中,此类将在容器启动期间被加载并实例化,并由任何 Servlet 3.0 兼容容器调用其 onStartup 方法。这是通过 JAR 服务 API {@link ServiceLoader#load(Class)} 方法检测 spring-web 模块的 META-INF/services/javax.servlet.ServletContainerInitializer
服务提供者配置文件来实现的。

请参阅 http://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider JAR Services API 文档以及 Servlet 3.0 Final Draft 规范的第8.2.4节完整的细节。

基本上所有内容都在文档中,它是 Servlet 规范的一部分,用于检测SpringServletContainerInitializer哪个实现ServletContainerInitializer,因此这一切都取决于容器执行检测这些类的工作。