• Spring MVC 源码 分析


    spring web

     源码 

    @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(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
                throws ServletException {
    
            List<WebApplicationInitializer> initializers = new LinkedList<>();
    
            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)
                                    ReflectionUtils.accessibleConstructor(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;
            }
    
            servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
            AnnotationAwareOrderComparator.sort(initializers);
            for (WebApplicationInitializer initializer : initializers) {
                initializer.onStartup(servletContext);
            }
        }
    
    }
    WebApplicationInitializer 有4个实现类 

     

     1. AbstractContextLoaderInitializer 

    public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
    
        /** Logger available to subclasses */
        protected final Log logger = LogFactory.getLog(getClass());
    
    
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            registerContextLoaderListener(servletContext);    //注册 监听器  
        }
    
        /**
         * Register a {@link ContextLoaderListener} against the given servlet context. The
         * {@code ContextLoaderListener} is initialized with the application context returned
         * from the {@link #createRootApplicationContext()} template method.
         * @param servletContext the servlet context to register the listener against
         */
        protected void registerContextLoaderListener(ServletContext servletContext) {
            WebApplicationContext rootAppContext = createRootApplicationContext();    //创建web根容器  
            if (rootAppContext != null) {
                ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);  
                listener.setContextInitializers(getRootApplicationContextInitializers());
                servletContext.addListener(listener);          //添加监听器
            }
            else {
                logger.debug("No ContextLoaderListener registered, as " +
                        "createRootApplicationContext() did not return an application context");
            }
        }
    
        /**
         * Create the "<strong>root</strong>" application context to be provided to the
         * {@code ContextLoaderListener}.
         * <p>The returned context is delegated to
         * {@link ContextLoaderListener#ContextLoaderListener(WebApplicationContext)} and will
         * be established as the parent context for any {@code DispatcherServlet} application
         * contexts. As such, it typically contains middle-tier services, data sources, etc.
         * @return the root application context, or {@code null} if a root context is not
         * desired
         * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer
         */
        @Nullable
        protected abstract WebApplicationContext createRootApplicationContext();
    
        /**
         * Specify application context initializers to be applied to the root application
         * context that the {@code ContextLoaderListener} is being created with.
         * @since 4.2
         * @see #createRootApplicationContext()
         * @see ContextLoaderListener#setContextInitializers
         */
        @Nullable
        protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
            return null;
        }
    
    }

    2 .  AbstractDispatcherServletInitializer 

    public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {
        public static final String DEFAULT_SERVLET_NAME = "dispatcher";
    
        public AbstractDispatcherServletInitializer() {
        }
    
        public void onStartup(ServletContext servletContext) throws ServletException {
            super.onStartup(servletContext);
            this.registerDispatcherServlet(servletContext);
        }
    
        protected void registerDispatcherServlet(ServletContext servletContext) {
            String servletName = this.getServletName();
            Assert.hasLength(servletName, "getServletName() must not return null or empty");
            WebApplicationContext servletAppContext = this.createServletApplicationContext();
            Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");
            FrameworkServlet dispatcherServlet = this.createDispatcherServlet(servletAppContext);
            Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
            dispatcherServlet.setContextInitializers(this.getServletApplicationContextInitializers());
            Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);    //添加servlet 
            if (registration == null) {
                throw new IllegalStateException("Failed to register servlet with name '" + servletName + "'. Check if there is another servlet registered under the same name.");
            } else {
                registration.setLoadOnStartup(1);
                registration.addMapping(this.getServletMappings());  //添加mapping
                registration.setAsyncSupported(this.isAsyncSupported());
                Filter[] filters = this.getServletFilters();
                if (!ObjectUtils.isEmpty(filters)) {
                    Filter[] var7 = filters;
                    int var8 = filters.length;
    
                    for(int var9 = 0; var9 < var8; ++var9) {
                        Filter filter = var7[var9];
                        this.registerServletFilter(servletContext, filter);
                    }
                }
    
                this.customizeRegistration(registration);
            }
        }
    
        protected String getServletName() {
            return "dispatcher";
        }
    
        protected abstract WebApplicationContext createServletApplicationContext();
    
        protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
            return new DispatcherServlet(servletAppContext);
        }
    
        @Nullable
        protected ApplicationContextInitializer<?>[] getServletApplicationContextInitializers() {
            return null;
        }
    
        protected abstract String[] getServletMappings();
    
        @Nullable
        protected Filter[] getServletFilters() {
            return null;
        }
    
        protected javax.servlet.FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
            String filterName = Conventions.getVariableName(filter);
            javax.servlet.FilterRegistration.Dynamic registration = servletContext.addFilter(filterName, filter);
            if (registration == null) {
                for(int counter = 0; registration == null; ++counter) {
                    if (counter == 100) {
                        throw new IllegalStateException("Failed to register filter with name '" + filterName + "'. Check if there is another filter registered under the same name.");
                    }
    
                    registration = servletContext.addFilter(filterName + "#" + counter, filter);   //添加filter
                } 
            }
    
            registration.setAsyncSupported(this.isAsyncSupported());
            registration.addMappingForServletNames(this.getDispatcherTypes(), false, new String[]{this.getServletName()});
            return registration;
        }
    
        private EnumSet<DispatcherType> getDispatcherTypes() {
            return this.isAsyncSupported() ? EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC) : EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE);
        }
    
        protected boolean isAsyncSupported() {
            return true;
        }
    
        protected void customizeRegistration(Dynamic registration) {
        }
    }

    3   AbstractAnnotationConfigDispatcherServletInitializer 

    public abstract class AbstractAnnotationConfigDispatcherServletInitializer extends AbstractDispatcherServletInitializer {
        public AbstractAnnotationConfigDispatcherServletInitializer() {
        }
    
        @Nullable
        protected WebApplicationContext createRootApplicationContext() {
            Class<?>[] configClasses = this.getRootConfigClasses();
            if (!ObjectUtils.isEmpty(configClasses)) {
                AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();   //类似spring 中配置文件
                context.register(configClasses);
                return context;
            } else {
                return null;
            }
        }
    
        protected WebApplicationContext createServletApplicationContext() {
            AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
            Class<?>[] configClasses = this.getServletConfigClasses();
            if (!ObjectUtils.isEmpty(configClasses)) {
                context.register(configClasses);
            }
    
            return context;
        }
    
        @Nullable
        protected abstract Class<?>[] getRootConfigClasses();
    
        @Nullable
        protected abstract Class<?>[] getServletConfigClasses();
    }
    public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {

    /** Logger available to subclasses */
    protected final Log logger = LogFactory.getLog(getClass());


    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
    registerContextLoaderListener(servletContext);
    }

    /**
    * Register a {@link ContextLoaderListener} against the given servlet context. The
    * {@code ContextLoaderListener} is initialized with the application context returned
    * from the {@link #createRootApplicationContext()} template method.
    * @param servletContext the servlet context to register the listener against
    */
    protected void registerContextLoaderListener(ServletContext servletContext) {
    WebApplicationContext rootAppContext = createRootApplicationContext();
    if (rootAppContext != null) {
    ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
    listener.setContextInitializers(getRootApplicationContextInitializers());
    servletContext.addListener(listener);
    }
    else {
    logger.debug("No ContextLoaderListener registered, as " +
    "createRootApplicationContext() did not return an application context");
    }
    }

    /**
    * Create the "<strong>root</strong>" application context to be provided to the
    * {@code ContextLoaderListener}.
    * <p>The returned context is delegated to
    * {@link ContextLoaderListener#ContextLoaderListener(WebApplicationContext)} and will
    * be established as the parent context for any {@code DispatcherServlet} application
    * contexts. As such, it typically contains middle-tier services, data sources, etc.
    * @return the root application context, or {@code null} if a root context is not
    * desired
    * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer
    */
    @Nullable
    protected abstract WebApplicationContext createRootApplicationContext();

    /**
    * Specify application context initializers to be applied to the root application
    * context that the {@code ContextLoaderListener} is being created with.
    * @since 4.2
    * @see #createRootApplicationContext()
    * @see ContextLoaderListener#setContextInitializers
    */
    @Nullable
    protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
    return null;
    }

    }
  • 相关阅读:
    Cocos Creator Editor 第一个编辑器扩展(扩展菜单)
    Rider 设置
    unity 使用GameObject.SetActive(true)激活对象时,会在SetActive内部调用Awake和OnEnable函数
    unity/C# 结构体属性使用set和get访问器应注意的问题
    unity 自定义AssetImporter导入指定资源
    Duilib部分源码解析
    TreeView树形控件的使用
    JQuery 文档资源收集
    排序和搜索(一)插入排序系列
    字符相关类型和编码概念
  • 原文地址:https://www.cnblogs.com/qin1993/p/11928777.html
Copyright © 2020-2023  润新知