spring框架的WebApplicationInitializer接口

原创

疑问:为什么实现了WebApplicationInitializer接口的类,在自动时会自动执行其重写的onStart()方法?

第一步: 查看接口WebApplicationInitializer的API(spring-web-x.x.x.jar下),该接口只有一个方法: 
void onStartup(ServletContext servletContext) throws ServletException;

接口说明:

Interface to be implemented in Servlet 3.0+ environments in order to configure the ServletContext programmatically – as opposed to (or possibly in conjunction with) the traditional web.xml-based approach. 
Implementations of this SPI will be detected automatically by SpringServletContainerInitializer, which itself is bootstrapped automatically by any Servlet 3.0 container.

翻译过来,实现该接口可以在Servlet 3.0 +环境中以编程方式配置ServletContext,而不是(或结合)传统的基于web.xml文件配置。实现由SpringServletContainerInitializer SPI将自动检测到,这本身就是由任何Servlet 3.0容器自动引导。

第二步:查看类SpringServletContainerInitializer的API(同包下),该类实现了ServletContainerInitializer接口,重写了其void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException;方法

其方法代码如下:

@Override
    public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
            throws ServletException {

        List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

        if (webAppInitializerClasses != null) {
            for (Class<?> waiClass : webAppInitializerClasses) {
                // Be defensive: Some servlet containers provide us with invalid classes,
                // no matter what @HandlesTypes says...
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
                        WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((WebApplicationInitializer) waiClass.newInstance());
                    }
                    catch (Throwable ex) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
            return;
        }

        AnnotationAwareOrderComparator.sort(initializers);
        servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);

        for (WebApplicationInitializer initializer : initializers) {
            initializer.onStartup(servletContext);
        }
    }

类说明:

This class will be loaded and instantiated and have its onStartup(java.util.Set, javax.servlet.ServletContext) method invoked by any Servlet 3.0-compliant container during container startup assuming that the spring-web module JAR is present on the classpath. This occurs through the JAR Services API ServiceLoader.load(Class) method detecting the spring-web module’s META-INF/services/javax.servlet.ServletContainerInitializer service provider configuration file. See the JAR Services API documentation as well as section 8.2.4 of the Servlet 3.0 Final Draft specification for complete details.

翻译过来,这个类将被加载和实例化,其 onStartup(java.util.Set<java.lang.Class<?>>, javax.servlet.ServletContext)方法在任何Servlet 3.0兼容的容器在容器启动时被调用,当JAR的spring-web模块存在的classpath中。在当JAR服务APIServiceLoader.load(Class)方法检测spring-web模块的META-INF/services/javax.servlet.ServletContainerInitializer`服务提供者配置文件时发生。请参见JAR服务API文档以及部分8.2.4 Servlet 3.0的最终草案规范完整的细节。

正文到此结束