SpringMVC 第二章 - WebApplicationContext的初始化

上一篇章主要总结了SpringMVC在启动的时候,会去构造webApplicationContext对象,并且将该对象放入到ServletContext中,在web的整个生命周期中使用。在分析Spring MVC最重要的一个类DispatcherServlet的时候,在其父类初始化的时候,发现了webApplicationContext的初始化的方法,因此在这边总结一下。

 /**
   *  webApplicationContext的初始化
   */
    protected WebApplicationContext initWebApplicationContext() {

        WebApplicationContext rootContext =  WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        WebApplicationContext wac = null;

        // Step1 : 通过构造函数的注入进行初始化
        if (this.webApplicationContext != null) {
              wac = this.webApplicationContext;
              if (wac instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
                if (!cwac.isActive()) {
                    if (cwac.getParent() == null) {
                        cwac.setParent(rootContext);
                    }
                    configureAndRefreshWebApplicationContext(cwac);
                }
            }
        }

        // Step2: 通过contextAttribute进行初始化
        if (wac == null) {
            wac = findWebApplicationContext();
        }

        // Step3: 重新创建webApplicationContext实例
        if (wac == null) {
            wac = createWebApplicationContext(rootContext);
        }

        if (!this.refreshEventReceived) {
            onRefresh(wac);
        }

        if (this.publishContext) {
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
        }

        return wac;
    }

上面这份源码无非是在说明webApplicationContext是如何被构造的,默认还是使用反射的方式构建xmlWebApplicationContext实体类


  无论是通过构造函数注入还是单独创建,到最后都会对已经创建的webApplicationContext实例进行配置以及刷新
 protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);  # 上传
        initLocaleResolver(context);      #  国际化语言
        initThemeResolver(context);      #  页面主题(静态文件)
        initHandlerMappings(context);  #  初始化HandlerMappings (负责请求关系的转发)
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }

我这边只对比较感兴趣的initHandlerMappings(context) 和 initHandlerAdapters(context) 做解读。

initHandlerMappings(context)

      当客户端发出Request时,DispatcherServlet会将Request提交給HandlerMapping,然后HandlerMapping根据WebApplicationContext的配置来回传给DispatcherServlet相应的Controller
      默认情况下,SpringMVC会加载当前系统中所有实现了HandlerMapping接口的Bean

 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<HandlerMapping>(matchingBeans.values());
                AnnotationAwareOrderComparator.sort(this.handlerMappings);
            }
        } else {
            try {
                HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
                this.handlerMappings = Collections.singletonList(hm);
            } catch (NoSuchBeanDefinitionException ex) {

            }
        }

        if (this.handlerMappings == null) {
            this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
        }
    }

initHandlerAdapters(context) 这个方法与上面的方法类似,获取适配器,Spring默认配置了3个适配器
(1)http请求处理器适配器:HttpRequestHandlerAdapter
(2)简单控制器处理器适配器:SimpleControllerHandlerAdapter
(3)注解方法处理器适配器:AnnotationMethodHandlerAdapter

时间: 2024-10-29 10:28:47

SpringMVC 第二章 - WebApplicationContext的初始化的相关文章

第二章、进程的描述与控制

第二章.进程的描述与控制 2.1 前趋图和程序执行 2.1.1 前趋图 概念: 所谓前趋图:指一个有向无循环图(DAG),它用于描述进程之间执行的先后顺序. 2.1.2 程序顺序执行 特征: 顺序性 封闭性:指程序在封闭的环境中运行,程序运行时独占全机资源,资源的状态只有本程序才能改变,程序一旦开始执行,其执行结果不受外界因素影响 可再现性:只要条件相同还会得到相同的执行结果. 2.1.3 程序并发执行 特征: 间断性 失去封闭性 不可在现性 2.2进程的描述 2.2.1 进程的定义和特征 定义

&amp;gt; 第二章 NGWS Runtime 技术基础(rainbow 翻译) (转自重粒子空

<<展现C#>> 第二章 NGWS Runtime 技术基础(rainbow 翻译)   出处:http://www.informit.com/matter/ser0000001/chapter1/ch02.shtml 正文: 第二章  NGWS  runtime 技术基础     既然你已经具有了C#全面的印象,我也想让你了解NGWS runtime的全貌.C#依靠由NGWS提供的运行时:因此,有必要知道运行时如何工作,以及它背后所蕴含的概念.    所以,这一章分为两部分--它

《.net编程先锋C#》第二章 理论基础-公用语言 运行环境(转)

编程 第二章 理论基础-公用语言 运行环境既然你已经具有了C#全面的印象,我也想让你了解NGWS runtime的全貌.C#依靠由NGWS提供的运行时:因此,有必要知道运行时如何工作,以及它背后所蕴含的概念.所以,这一章分为两部分--它们是所有的概念和使用的基础.两部分的内容虽然有些重叠,但它有助于加深理解正在学习的概念. 2.1 NGWS RuntimeNGWS和NGWS Runtime为你提供了一种运行时环境.该运行时管理执行代码,并提供了使编程更容易的服务.只要你的编译器支持这种运行时,你

Java初级笔记-第二章

第二章 Java的基本数据类型.运算符及表达式 2.1 标识符 标识符是程序员对程序中的各个元素加以命名时使用的命名记号. A-Z.a-z.0-9._.$ 第一个字母不可以是数字(0-9), 标识符中的字符是区分大小写的,Java的代码是严格区分大小写的.  标识符不可以是中文. 2.2 标识符的使用规范 不可以用关键字.保留字和中文字符 标识符使用在:常量名.变量名.类名(文件名).包名.方法名 命名规则:  包名全小写.Eg:axx.bxxx.cxx  类名单词的首字母大写(大驼峰规则

经典中的品味:第二章 C++基本的对象,类型和值(上)

2.1 一个简单问候的例子 最常见的就是keyBorad input(键盘输入).从HelloWorldd的输出,我们也想得到用户的输入.通常,实行中的程序会给它的输入产生输出.例如,输入你的名字,输出 一句问候.有时候它就在身边,像我最爱的苹果手机一样.人机交互就是那么简单~ 图2.1.1 人机交互(.net) 回 到技术点,为了读取用户输入的数据,我们需要在计算机内存中某个地方放置读取所需的内容.这就是对象(Class).对象是什么,对象时一个某种类型的内 存区域.其中类型则确定了对象的信息

java 程序性能优化《第二章》设计优化 2.1善用设计模式 1 单例模式

java 程序性能优化<第二章>设计优化 2.1善用设计模式 1 单例模式 设计模式是前人工作的总结和提炼.通常,被人们广泛流传的设计模式都是对某一特定问题的成熟的解决方案.如果能合理的使用设计模式,不仅能使系统更容易被他人理解,同时也能使系统拥有更加合理的结构.本节总结归纳了一些经典的设计模式,并详细说明它们与软件性能之间的关系. 2.1.1 单例模式 单例模式是设计模式中使用最为普遍的模式之一.它是一种对象创建模式,用于生产一个对象的具体实现,它可以确保系统中一个类只产生一个实例.在Jav

第二章 单元测试的基本概念和核心技法

第二章 单元测试的基本概念和核心技法 2.1 良好的单元测试--定义 我们已经了解了程序员需要单元测试,下面我们来给单元测试作一个完整的定义: ● 定义: 单元测试是一段自动执行的代码,它调用被测类或被测方法,然后验证关于被测类或被测方法逻辑行为的假设确实成立.单元测试几乎总是用单元测试框架(unit testing framework)来写就的,单元测试是易于写就.执行快速.完全自动化.值得依赖.易于阅读并易于维护的. 这个定义有点长,但是它却包含了大量重要信息: ● 单元测试的测试重点是被测

Knockout应用开发指南 第二章:监控属性(Observables)

原文:Knockout应用开发指南 第二章:监控属性(Observables) 关于Knockout的3个重要概念(Observables,DependentObservables,ObservableArray),本人无法准确表达它的准确含义,所以暂定翻译为(监控属性.依赖监控属性和监控数组),如果有好的建议请指正,多谢. 1     创建带有监控属性的view model Observables Knockout是在下面三个核心功能是建立起来的: 监控属性(Observables)和依赖跟踪

Docker概述 第二章

本文讲的是Docker概述 第二章,[编者的话]在本次介绍Docker的迷你系列第一章中,我们了解了什么使Docker如此特别.虚拟机与容器之间的区别和组成Docker的主要组件.在本博文中,我们将直接与一些容器接触.尤其是,我们将展示如何启动一个容器,如何使用Dockerfile构建镜像,如何与注册服务(registries)打交道,并介绍数据卷(data volumes)的基本概念. 启动容器 在启动一个容器之前,你需要先从注册服务中拉取 $ docker pull alpine 启动容器执