zoukankan      html  css  js  c++  java
  • WebApplicationInitializer (spring 3.x.x以上版本)

    实现WebApplicationinitializer接口的类都可以在web应用程序启动时被加载。

    那么来想一个问题:为什么实现了WebApplicationInitializer这个接口后,onStartup方法就会自动执行?

    我们来简单分析一下它的实现原理,下面先贴上WebApplicationInitializer接口相关代码:

    servlet的ServletContainerInitializer接口:

    package javax.servlet;
    
    import java.util.Set;
    
    public interface ServletContainerInitializer {
    
        /**
         * Receives notification during startup of a web application of the classes
         * within the web application that matched the criteria defined via the
         * {@link javax.servlet.annotation.HandlesTypes} annotation.
         *
         * @param c     The (possibly null) set of classes that met the specified
         *              criteria
         * @param ctx   The ServletContext of the web application in which the
         *              classes were discovered
         *
         * @throws ServletException If an error occurs
         */
        void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException;
    }
    SpringServletContainerInitializer 类(从本类开始以下代码都是spring的代码):
    package org.springframework.web;
    
    import java.lang.reflect.Modifier;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.ServiceLoader;
    import java.util.Set;
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.HandlesTypes;
    
    import org.springframework.core.annotation.AnnotationAwareOrderComparator;
    @HandlesTypes(WebApplicationInitializer.class)
    public class SpringServletContainerInitializer implements ServletContainerInitializer {
    
        /**
         * Delegate the {@code ServletContext} to any {@link WebApplicationInitializer}
         * implementations present on the application classpath.
         *
         * <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)},
         * Servlet 3.0+ containers will automatically scan the classpath for implementations
         * of Spring's {@code WebApplicationInitializer} interface and provide the set of all
         * such types to the {@code webAppInitializerClasses} parameter of this method.
         *
         * <p>If no {@code WebApplicationInitializer} implementations are found on the
         * classpath, this method is effectively a no-op. An INFO-level log message will be
         * issued notifying the user that the {@code ServletContainerInitializer} has indeed
         * been invoked but that no {@code WebApplicationInitializer} implementations were
         * found.
         *
         * <p>Assuming that one or more {@code WebApplicationInitializer} types are detected,
         * they will be instantiated (and <em>sorted</em> if the @{@link
         * org.springframework.core.annotation.Order @Order} annotation is present or
         * the {@link org.springframework.core.Ordered Ordered} interface has been
         * implemented). Then the {@link WebApplicationInitializer#onStartup(ServletContext)}
         * method will be invoked on each instance, delegating the {@code ServletContext} such
         * that each instance may register and configure servlets such as Spring's
         * {@code DispatcherServlet}, listeners such as Spring's {@code ContextLoaderListener},
         * or any other Servlet API componentry such as filters.
         *
         * @param webAppInitializerClasses all implementations of
         * {@link WebApplicationInitializer} found on the application classpath
         * @param servletContext the servlet context to be initialized
         * @see WebApplicationInitializer#onStartup(ServletContext)
         * @see AnnotationAwareOrderComparator
         */
        @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);
            }
        }
    
    }

    WebApplicationInitializer接口(本文讨论的接口):

    package org.springframework.web;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException
    public interface WebApplicationInitializer {
    
        /**
         * Configure the given {@link ServletContext} with any servlets, filters, listeners
         * context-params and attributes necessary for initializing this web application. See
         * examples {@linkplain WebApplicationInitializer above}.
         * @param servletContext the {@code ServletContext} to initialize
         * @throws ServletException if any call against the given {@code ServletContext}
         * throws a {@code ServletException}
         */
        void onStartup(ServletContext servletContext) throws ServletException;
    
    }

    javax.servlet.ServletContainerInitializer文件(在路径:spring-framework/spring-web/src/main/resources/META-INF/services/下

    该文件文件名就是“javax.servlet.ServletContainerInitializer”,其内容只有下面这行

         并且必须在 spring-web-X.X.X.RELEASE-sources.jar 文件下,的META_INF/services路径下有个名为“ javax.servlet.ServletContainerInitializer”的文件,文件中的内容与 ServletContainerIntializer的实现类全限定名相同(请参考上面贴出的代码)。这样,web应用启动时,程序就会找到WebApplicationInitializer这个接口的实现类,并调用onStartup方法。

    如果说得不对的地方,请指正,谢谢

    参考:

    http://blog.csdn.net/sunhuwh/article/details/25441217

    http://blog.csdn.net/sunhuwh/article/details/25504061

    spring源码:https://github.com/spring-projects/spring-framework

    原创文章,转载请注明:http://www.cnblogs.com/langtianya/p/5393633.html

  • 相关阅读:
    Javascript函数式编程要掌握的知识点讲解
    任务
    怎么添加项目到SVN上面
    随便写一点最近开发遇到的问题和解决方法 大部分关于laravel和php
    laravel 将数组转化成字符串 再把字符串转化成数组
    laravel 配置了自己的域名以后, localhost 无法访问 404 not found 的解决方法
    实习日记15
    php接收post过来的 json数据 例子
    数据库如何让自增id重置
    C#连接MySQL数据库
  • 原文地址:https://www.cnblogs.com/langtianya/p/5393633.html
Copyright © 2011-2022 走看看