wittyResry / myIssue

My issue mark down^_^ 欢迎吐槽,讨论~~
https://github.com/wittyResry/myIssue/issues
The Unlicense
5 stars 1 forks source link

SpringMVC #32

Open wittyResry opened 7 years ago

wittyResry commented 7 years ago

HttpServletBean

wittyResry commented 7 years ago

FrameworkServlet

关于重写 initServletBean() 方法

public interface WebApplicationContext extends ApplicationContext {
    ServletContext getServletContext();
}
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    String getId();
    String getApplicationName();
    String getDisplayName();
    long getStartupDate();
    ApplicationContext getParent();

    /**
     * Expose AutowireCapableBeanFactory functionality for this context.
     * <p>This is not typically used by application code, except for the purpose of
     * initializing bean instances that live outside of the application context,
     * applying the Spring bean lifecycle (fully or partly) to them.
     * <p>Alternatively, the internal BeanFactory exposed by the
     * {@link ConfigurableApplicationContext} interface offers access to the
     * {@link AutowireCapableBeanFactory} interface too. The present method mainly
     * serves as a convenient, specific facility on the ApplicationContext interface.
     * <p><b>NOTE: As of 4.2, this method will consistently throw IllegalStateException
     * after the application context has been closed.</b> In current Spring Framework
     * versions, only refreshable application contexts behave that way; as of 4.2,
     * all application context implementations will be required to comply.
     * @return the AutowireCapableBeanFactory for this context
     * @throws IllegalStateException if the context does not support the
     * {@link AutowireCapableBeanFactory} interface, or does not hold an
     * autowire-capable bean factory yet (e.g. if {@code refresh()} has
     * never been called), or if the context has been closed already
     * @see ConfigurableApplicationContext#refresh()
     * @see ConfigurableApplicationContext#getBeanFactory()
     */
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
wittyResry commented 7 years ago

DispatcherServlet

onRefresh()

@Override
protected void onRefresh(ApplicationContext context) {
    initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

下面分析下initHandlerMappings(context)

Using a handler mapping you can map incoming web requests to appropriate handlers:当一个请求过来的时候,HandlerMapping 负责把处理该请求的 handler 找到, HandlerAdapter 则负责执行这个方法。 
The strategy interface HandlerAdapter takes the role of invoking handler methods selected by some HandlerMapping. HandlerAdapter负责执行HandlerMapping获取的handler方法
This allows for different types of controllers use different method invokation strategies. and URL mapping strategies are possible.
The first HandlerAdapter that supports the handler object (controller or method) is used to invoke the handler.
Spring MVC supports several types of controllers, including: annotation defined controllers (with @Controller), the WebFlow FlowExecutor etc.
AnnotationMethodHandlerAdapter

AnnotationMethodHandlerAdapter adapts HTTP requests to handler methods annotated with @RequestMapping. It introspects required input arguments for handlers, and interprets output values. This the HandlerAdapter configured by default.
The AnnotationMethodHandlerAdapter can be used with controller with multiple handler methods in a variety of powerful ways.

doService()

@Override
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

        try {
            doDispatch(request, response);
        }
}
    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;
                }
                //像之前说的,拿到处理该请求的 HandlerMapping。
                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;
                }
                // Actually invoke the handler.
                //具体调用该方法处理这个请求,并且返回一个 ModelAndView 对象,该对象包含了视图和数据
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applyDefaultViewName(processedRequest, mv);
                /** 利用视图解析器对视图对象 mv 进行解析,并且 response 返回。*/
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }
wittyResry commented 6 years ago

在Spring MVC里,如果把@ModelAttribute放在方法的注解上时,代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法。