SpringMVC源码剖析(一) DispatcherServlet

一、DispatcherServlet构造方法

DispatcherServlet有两个构造方法,一个无参数的构造方法和一个WebApplicationContext参数的构造方法,如下代码:

    public DispatcherServlet() {
    }

    public DispatcherServlet(WebApplicationContext webApplicationContext) {
        super(webApplicationContext);
    }

其中重点看有参数的构造方法,其主要是调用其父类的构造方法,DispatcherServlet是继承父类FrameworkServlet,我们看下FrameworkServlet的构造方法,其代码如下:

    public FrameworkServlet(WebApplicationContext webApplicationContext) {
        this.contextClass = DEFAULT_CONTEXT_CLASS;
        this.publishContext = true;
        this.publishEvents = true;
        this.threadContextInheritable = false;
        this.dispatchOptionsRequest = false;
        this.dispatchTraceRequest = false;
        this.webApplicationContextInjected = false;
        this.refreshEventReceived = false;
        this.contextInitializers = new ArrayList();
        this.webApplicationContext = webApplicationContext;
    }

其中DEFAULT_CONTEXT_CLASS是XmlWebApplicationContext的类,主要是对其中一些属性进行赋值。

二、属性设置

DispatcherServlet通过set方法设置了一些属性,这些属性的默认值都为true,如下:

1、detectAllHandlerMappings           

2、detectAllHandlerAdapters

3、detectAllHandlerExceptionResolvers

4、detectAllViewResolvers

5、throwExceptionInfoHandlerFound

6、cleanupAfterInclude

三、初始化

DispatcherServlet中有一个onRefresh方法,其主要调用的是initStrategies(context)方法

再看一下initStrategies(context)方法的源码

    protected void initStrategies(ApplicationContext context) {
        this.initMultipartResolver(context);
        this.initLocaleResolver(context);
        this.initThemeResolver(context);
        this.initHandlerMappings(context);
        this.initHandlerAdapters(context);
        this.initHandlerExceptionResolvers(context);
        this.initRequestToViewNameTranslator(context);
        this.initViewResolvers(context);
        this.initFlashMapManager(context);
    }

主要做的是一些文件上传解析器,HandlerMappings等的一些初始化,会调用这些组件的私有初始化方法进行初始化。

例如文件上传解析器初始化initMultipartResolver方法

   private void initMultipartResolver(ApplicationContext context) {
        try {
            this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
            }
        } catch (NoSuchBeanDefinitionException var3) {
            this.multipartResolver = null;
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided");
            }
        }

    }

首先从context中通过getBean方法获取一个multipartResolver对象,并赋值到DispatcherServlet中的mutipartResolver属性中。如果出现异常,会将mutipartResolver属性设为空,并且打印日志。

方法initLocaleResolver和initThemeResolver和其类似。

看一下方法initHandlerMappings(ApplicationContext context)

    private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;
        if (this.detectAllHandlerMappings) {
            Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerMappings = new ArrayList(matchingBeans.values());
                OrderComparator.sort(this.handlerMappings);
            }
        } else {
            try {
                HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
                this.handlerMappings = Collections.singletonList(hm);
            } catch (NoSuchBeanDefinitionException var3) {
                ;
            }
        }

        if (this.handlerMappings == null) {
            this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("No HandlerMappings found in servlet '" + this.getServletName() + "': using default");
            }
        }

    }

首先将handlerMappings设置为空,创建了一个Map<String,HandlerMapping>,String和HandlerMapping的key-value的map,通过BeanFactoryUtils的方法beansOfTypeIncludingAncestors,这个方法的作用是根据类型寻找bean,找出所有匹配类型的beanName,取出匹配bean的值,放入handlerMappings的ArrayList数组中,并且进行排序,这个排序底层调用的是Collections.sort()的方法,传入了一个OrderComparator的比较器。

如果没有找到handlerMapping,会使用一个默认的BeanNameUrlHandlerMapping,确保有至少有一个HandlerMapping

四、get方法

DispatcherServlet定义了获取这些属性的get方法

五、默认策略方法

创建一个默认的策略,其默认实现使用AutoworeCapableBeanFactory的createBean方法

	protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
		return context.getAutowireCapableBeanFactory().createBean(clazz);
	}

猜你喜欢

转载自blog.csdn.net/weixin_38938982/article/details/80539171