servlet容器如何找到WebApplicationInitializer实现

时间:2015-01-24 22:42:32

标签: java spring spring-mvc servlets servlet-3.0

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

2 个答案:

答案 0 :(得分:9)

我假设您了解java SPI以及用于加载实现的java.util.ServiceLoader实用程序类的方式。其他please read it

但简而言之,这个答案只是理解:如果有一个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为Web应用程序初始化ServletContext时,它将生成这样的事件,该事件将通知ContextConfig甚至是监听方法。然后它会触发 它自己的processServletContainerInitializers方法,它扫描JAR以获取ServletContainerInitializer实现。 它通过将此职责委派给 WebappServiceLoader (Java的JAR ServiceLoader的变体)来实现这一点,他实际上负责从加载 ServletContainerInitializer 实现。 WEB-INF / lib 罐子。

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

  1. Tomcat初始化ServletContext

  2. 使用此上下文启动事件

    通知
  3. ContextConfig

  4. 委托服务加载 WebappServiceLoader<ServletContainerInitializer>

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

  6. 一旦加载返回步骤3,ContextConfig将调用 实施&#39;(这里SpringServletContainerInitializer onStartup 方法将完成剩下的工作。
  7. HTH!

答案 1 :(得分:1)

来自docs:

  

该SPI的实现将由
自动检测   SpringServletContainerInitializer,它本身就是自举的   由任何Servlet 3.0容器自动完成。看到   SpringServletContainerInitializer或此引导的详细信息   机构。

  

运作机制

  SpringServletContainerInitializer

     

这个类将被加载   实例化并由any调用其onStartup方法   假设在容器启动期间符合Servlet 3.0标准的容器   spring-web模块JAR存在于类路径中。   这通过JAR服务API {@link发生   ServiceLoader #load(Class)}方法检测弹簧网   模块   META-INF /服务/ javax.servlet.ServletContainerInitializer
  服务提供商配置文件。

     

见   http://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider JAR服务API文档以及 8.2.4 部分   有关完整详细信息,请参阅Servlet 3.0最终草案规范。

所有文档都基本上是Servlet规范的一部分,用于检测实现SpringServletContainerInitializer的{​​{1}},所以它一直到容器执行检测这些类的工作。