首页 > 代码库 > Spring源码阅读:Spring MVC 初始化

Spring源码阅读:Spring MVC 初始化

 

    通过之前的源码学习,了解了Spring的两个核心IOC和AOP。也了解到系统初始化时,就已经将所有applicationContext.xml中的bean Definintion加载并初始化了。

如果使用了SpringMVC框架,MVC框架指定的namespace-servlet.xml也已经被初始化了。

    使用过SpringMVC,都知道需要在web.xml配置配置DispatcherServlet,它是处理请求的入口。Servlet是单例的,系统指挥在第一次处理用户请求时初始化Servlet对象。那么DispatcherServlet初始化时都做了哪些工作呢?我们在namespace-servlet.xml中配置的视图解析器,注解处理器都是怎样被DispatcherServlet使用的呢?

 

DispatcherServlet的类型继承关系:

 

   

通过对DispatcherServlet及其父类的源码的阅读,了解到初始化的过程是这个样子的:

 

 

也就是说初始化DispatcherServlet的过程中要调用到DispatcherServlet对象的initStrategies()方法,下面来看看这个方法都干了啥:

 

DispatcherServlet定义了这些变量:

/** MultipartResolver used by this servlet */   private MultipartResolver multipartResolver;    /** LocaleResolver used by this servlet */   private LocaleResolver localeResolver;    /** ThemeResolver used by this servlet */   private ThemeResolver themeResolver;    /** List of HandlerMappings used by this servlet */   private List<HandlerMapping> handlerMappings;    /** List of HandlerAdapters used by this servlet */   private List<HandlerAdapter> handlerAdapters;    /** List of HandlerExceptionResolvers used by this servlet */   private List<HandlerExceptionResolver> handlerExceptionResolvers;    /** RequestToViewNameTranslator used by this servlet */   private RequestToViewNameTranslator viewNameTranslator;    /** List of ViewResolvers used by this servlet */   private List<ViewResolver> viewResolvers; 

 

initStrategies就是要初始化DispaterServlet中的变量的:

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

  这样就有疑问了:Servlet应该是一个无状态的类才能保证Servlet对象的线程安全性。而DispatcherServlet中定义了这么多变量,这样DispatcherServlet就不是线程就安全的类了。

    其实这个担忧是不必要的,在initStrategies方法中,是将DispatcherServlet中定义的变量进行初始化,这个方法只会调用一次,而在整个系统中,也只有这一个地方会调用这个方法。所以initStrategies内部的几个方法也只会被调用一次。而正是这一次调用就将相关的变量全部赋值。所以是不用担心线程安全的问题。

 

    这个方法为啥要传递一个ApplicationContext参数呢?

经过之前对于IOC容器初始化的分析了解到,在IOC初始化时,就已经将所有的Bean初始化了,这里要做的是将那些初始化完毕的bean从IOC容器ApplicationContext获取(context.getBean("beanName"))然后赋值给DispatcherServlet中的相关变量即可。