美文网首页
Spring MVC中核心Servlet继承图

Spring MVC中核心Servlet继承图

作者: binge1024 | 来源:发表于2017-04-21 17:28 被阅读0次

    核心Servlet继承图


    XXXAware在 spring中是可以感知的。既XXXAare就是告诉spring,要从其容器中拿到XXX。例如ApplicationContextAware中只有一个方法为setApplicationContext(ApplicationContext applicationContext)。如果需要ApplicationContext,只需要实现ApplicationContext接口中setApplicationContext()方法。spring会自动调用setApplicationContext()方法将ApplicationContext传递给调用者。EnvironmentCapable是告诉spring,有提供Environment的能力。因此当Spring需要Environment的时候只需要实现EnvironmentCapable接口的getEnvironment()方法。

    HttpServletBean中的init()方法

    /**
         * Map config parameters onto bean properties of this servlet, and
         * invoke subclass initialization.
         * @throws ServletException if bean properties are invalid (or required
         * properties are missing), or if subclass initialization fails.
         */
        @Override
        public final void init() throws ServletException {
            if (logger.isDebugEnabled()) {
               logger.debug("Initializing servlet '" + getServletName() + "'");
            }
    
            // Set bean properties from init parameters.
            try {
               PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
               BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
               ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
                bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
               initBeanWrapper(bw);
               bw.setPropertyValues(pvs, true);
            }
            catch (BeansException ex) {
               logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
               throw ex;
            }
    
            // Let subclasses do whatever initialization they like.
            initServletBean();
    
            if (logger.isDebugEnabled()) {
               logger.debug("Servlet '" + getServletName() + "' configured successfully");
            }
        }
    

    BeanWrapper是spring提供可以去操作javaBean属性的工具他可以直接修改一个对象属性的的值。

    /**
     *
     * @author cheng
     *
     */
    public class User {
    
        private String username;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public static void main(String[] args) {
            User user = new User();
            BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(user);
            beanWrapper.setPropertyValue("username", "xiaocheng");
            System.out.println(user.getUsername());
    
            PropertyValue propertyValue = new PropertyValue("username", "cheng");
            beanWrapper.setPropertyValue(propertyValue);
            System.out.println(user.getUsername());
        }
    }
    

    FrameworkServlet 由上面的分析可知Framework的初始化入口为initServletBean

    /**
         * Overridden method of {@link HttpServletBean}, invoked after any bean properties
         * have been set. Creates this servlet's WebApplicationContext.
         */
        @Override
        protected final void initServletBean() throws ServletException {
            getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
            if (this.logger.isInfoEnabled()) {
                this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
            }
            long startTime = System.currentTimeMillis();
    
            try {
               this.webApplicationContext = initWebApplicationContext();
               initFrameworkServlet();
            }
            catch (ServletException ex) {
               this.logger.error("Context initialization failed", ex);
               throw ex;
            }
            catch (RuntimeException ex) {
               this.logger.error("Context initialization failed", ex);
               throw ex;
            }
    
            if (this.logger.isInfoEnabled()) {
               long elapsedTime = System.currentTimeMillis() - startTime;
                this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
                       elapsedTime + " ms");
            }
        }
    

    initWebApplicationContext()方法

    /**
         * Initialize and publish the WebApplicationContext for this servlet.
         * <p>Delegates to {@link #createWebApplicationContext} for actual creation
         * of the context. Can be overridden in subclasses.
         * @return the WebApplicationContext instance
         * @see #FrameworkServlet(WebApplicationContext)
         * @see #setContextClass
         * @see #setContextConfigLocation
         */
        protected WebApplicationContext initWebApplicationContext() {
            WebApplicationContext rootContext =
                   WebApplicationContextUtils.getWebApplicationContext(getServletContext());
            WebApplicationContext wac = null;
    
            if (this.webApplicationContext != null) {
               // A context instance was injected at construction time -> use it
               wac = this.webApplicationContext;
               if (wac instanceof ConfigurableWebApplicationContext) {
                   ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
                   if (!cwac.isActive()) {
                       // The context has not yet been refreshed -> provide services such as
                       // setting the parent context, setting the application context id, etc
                       if (cwac.getParent() == null) {
                           // The context instance was injected without an explicit parent -> set
                           // the root application context (if any; may be null) as the parent
                           cwac.setParent(rootContext);
                       }
                       configureAndRefreshWebApplicationContext(cwac);
                   }
               }
            }
            if (wac == null) {
               // No context instance was injected at construction time -> see if one
               // has been registered in the servlet context. If one exists, it is assumed
               // that the parent context (if any) has already been set and that the
               // user has performed any initialization such as setting the context id
               wac = findWebApplicationContext();
            }
            if (wac == null) {
               // No context instance is defined for this servlet -> create a local one
               wac = createWebApplicationContext(rootContext);
            }
    
            if (!this.refreshEventReceived) {
               // Either the context is not a ConfigurableApplicationContext with refresh
               // support or the context injected at construction time had already been
               // refreshed -> trigger initial onRefresh manually here.
               onRefresh(wac);
            }
    
            if (this.publishContext) {
               // Publish the context as a servlet context attribute.
               String attrName = getServletContextAttributeName();
                getServletContext().setAttribute(attrName, wac);
               if (this.logger.isDebugEnabled()) {
                   this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
                           "' as ServletContext attribute with name [" + attrName + "]");
               }
            }
    
            return wac;
        }
    

    initWebApplicationContext()主要做了三件事1.获取spring的根容器rootContext。2.设置webApplicationContext并根据情况调用onRefresh()方法。3.将webApplicationContext设置在ServletContext中。

    DispatcherServlet

    onRefresh()方法为DispatcherServlet的入口方法。而onRefresh()方法有直接调用了initStrategies()方法。

     /**
         * This implementation calls {@link #initStrategies}.
         */
        @Override
        protected void onRefresh(ApplicationContext context) {
            initStrategies(context);
        }
    
        /**
         * Initialize the strategy objects that this servlet uses.
         * <p>May be overridden in subclasses in order to initialize further strategy objects.
         */
        protected void initStrategies(ApplicationContext context) {
            initMultipartResolver(context);
            initLocaleResolver(context);
            initThemeResolver(context);
            initHandlerMappings(context);
            initHandlerAdapters(context);
            initHandlerExceptionResolvers(context);
            initRequestToViewNameTranslator(context);
            initViewResolvers(context);
            initFlashMapManager(context);
        }
    

    doService()方法

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
             if (logger.isDebugEnabled()) {
                 String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
                 logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
                         " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
             }
    
             // Keep a snapshot of the request attributes in case of an include,
             // to be able to restore the original attributes after the include.
             Map<String, Object> attributesSnapshot = null;
             if (WebUtils.isIncludeRequest(request)) {
                 attributesSnapshot = new HashMap<String, Object>();
                 Enumeration<?> attrNames = request.getAttributeNames();
                 while (attrNames.hasMoreElements()) {
                     String attrName = (String) attrNames.nextElement();
                     if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
                         attributesSnapshot.put(attrName, request.getAttribute(attrName));
                     }
                 }
             }
    
             // Make framework objects available to handlers and view objects.
            request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
            request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
            request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
            request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
    
             FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
             if (inputFlashMap != null) {
                 request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
             }
            request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
            request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    
             try {
                 doDispatch(request, response);
             }
             finally {
                 if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
                     return;
                 }
                 // Restore the original attribute snapshot, in case of an include.
                 if (attributesSnapshot != null) {
                     restoreAttributesAfterInclude(request, attributesSnapshot);
                 }
             }
        }
    

    doDispatch()方法

    /**
         * Process the actual dispatching to the handler.
         * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
         * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
         * to find the first that supports the handler class.
         * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
         * themselves to decide which methods are acceptable.
         * @param request current HTTP request
         * @param response current HTTP response
         * @throws Exception in case of any kind of processing failure
         */
        protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
             HttpServletRequest processedRequest = request;
             HandlerExecutionChain mappedHandler = null;
             boolean multipartRequestParsed = false;
    
             WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
             try {
                 ModelAndView mv = null;
                 Exception dispatchException = null;
    
                 try {
                     processedRequest = checkMultipart(request);
                     multipartRequestParsed = (processedRequest != request);
    
                     // Determine handler for the current request.
                     mappedHandler = getHandler(processedRequest);
                     if (mappedHandler == null || mappedHandler.getHandler() == null) {
                         noHandlerFound(processedRequest, response);
                         return;
                     }
    
                     // Determine handler adapter for the current request.
                     HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
                     // Process last-modified header, if supported by the handler.
                     String method = request.getMethod();
                     boolean isGet = "GET".equals(method);
                     if (isGet || "HEAD".equals(method)) {
                         long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                         if (logger.isDebugEnabled()) {
                             logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                         }
                         if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                              return;
                         }
                     }
    
                     if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                         return;
                     }
    
                     try {
                         // Actually invoke the handler.
                         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                     }
                     finally {
                         if (asyncManager.isConcurrentHandlingStarted()) {
                              return;
                         }
                     }
    
                     applyDefaultViewName(request, mv);
                     mappedHandler.applyPostHandle(processedRequest, response, mv);
                 }
                 catch (Exception ex) {
                     dispatchException = ex;
                 }
                 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
             }
             catch (Exception ex) {
                 triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
             }
             catch (Error err) {
                 triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
             }
             finally {
                 if (asyncManager.isConcurrentHandlingStarted()) {
                     // Instead of postHandle and afterCompletion
                     mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                     return;
                 }
                 // Clean up any resources used by a multipart request.
                 if (multipartRequestParsed) {
                     cleanupMultipart(processedRequest);
                 }
             }
        }
    

    相关文章

      网友评论

          本文标题:Spring MVC中核心Servlet继承图

          本文链接:https://www.haomeiwen.com/subject/cgndzttx.html