Servlet前提

  1. Java规定了Servlet Container为每一个web app创建一个Servlet Context;而Servlet Context中又包含了诸多Servlet -- 其信息由ServletConfig对象持有,存储于Servlet Context的attribute中。
  2. Java提供了ServletContainerInitializer,用于发出通知:某个web应用已经处于启动阶段。--其实顾名思义,就是Servlet Container初始化时会调用这个接口的实现方法 onStartup。
  3. Java提供了五个Listener类 (ServletContextListener、ServletContextAttributeListener、ServletRequestListener、ServletRequestAttributeListener、HttpSessionListener、HttpSessionAttributeListener)来监听Servlet相关的行为。

Spring前提

  1. Spring Web,其实是创建了WebApplicationContext -- AnnotationConfigWebApplicationContext、XmlWebApplicationContext等。这是Root Application Context。
  2. Spring Web MVC,其实创建了DispatcherServlet,以及一个ServletApplicationContext。

务必注意,二者是不同的!简单的说,如果是注解驱动的,那Root Application Context对应的是除了@Controller之外的所有bean;而ServletApplicationContext 则只对应@Controller的bean。

如果不加以区分,可能会导致问题出现。(请搜索 父子容器)

开始

其实,明白了上述前提,就很好理解Spring MVC项目的流程了。(说明:这里是以Java-config形式说明的,但对于xml形式来说理论是一样的)

先来说说Java-config形式的Spring MVC项目都需要哪些配置:

1、Root Config (包含除了视图层之外的所有配置,可拆分出DataSourceConfig等)

@Configuration
@ComponentScan( basePackages = "win.larryzeal.spring",
excludeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = Controller.class ) )
public class AppConfig {
    // ...
}

2、MvcConfig

@Configuration
@ComponentScan( basePackages = "win.larryzeal.spring",
includeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = Controller.class ) )
@EnableWebMvc
public class MvcConfig {
// ...
}

3、WebAppInitializer(还可注册filter等,等价于web.xml)

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
protected Class<?>[] getRootConfigClasses(){
return new Class[]{AppConfig.class};
} @Override
protected Class<?>[] getServletConfigClasses(){
return new Class[]{MvcConfig.class};
} @Override
protected String[] getServletMappings(){
return new String[]{"/"};
} }

其实1和2都很好理解,3在使用上也好理解,但3封装了好几层。如果你点开AbstractAnnotationConfigDispatcherServletInitializer ,一直向上回溯,会发现最后的接口是 WebApplicationInitializer。

WebApplicationInitializer 这个接口是Spring提供的,它的javadoc说的很明白,它会被 SpringServletContainerInitializer 自动调用。

而 SpringServletContainerInitializer 则是Spring对 ServletContainerInitializer的实现! -- 对应Servlet前提2

所以,实际的逻辑是这样的:

① Servlet Container启动,调用ServletContainerInitializer的实现(这里就是SpringServletContainerInitializer ) ;

② SpringServletContainerInitializer 调用所有的 WebApplicationInitializer 实现 (这里就是我们提供的WebAppInitializer );

③ WebAppInitializer 设置了RootConfigClasses和ServletConfigClasses,以及DispatcherServlet的映射路径!

这里漏掉了Servlet前提3中所说的ServletContextListener,其实Spring也提供了它的实现类:ContextLoaderListener,在Servlet Container为web app创建Servlet Context时,自动创建Root WebApplicationContext。

鉴于这是一个Listener,我们需要将其注册到Servlet Container中才行,上面③已经替我们做了(见AbstractContextLoaderInitializer#registerContextLoaderListener)! -- 如果使用web.xml,实际上是需要手动注册一下的:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

懒得画图了,就这么着吧。

之前还有一篇,可以看看:

Spring 4 官方文档学习(十一)Web MVC 框架之编码式Servlet容器初始化

捋一捋Spring Web的源码思路的更多相关文章

  1. Spring IOC 容器源码分析系列文章导读

    1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...

  2. Spring IOC 容器源码分析

    声明!非原创,本文出处 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 S ...

  3. Spring IOC 容器源码分析(转)

    原文地址 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢 ...

  4. Spring IOC容器源码分析

    注:本文转自https://javadoop.com/post/spring-ioc Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容 ...

  5. 最简 Spring IOC 容器源码分析

    前言 BeanDefinition BeanFactory 简介 Web 容器启动过程 bean 的加载 FactoryBean 循环依赖 bean 生命周期 公众号 前言 许多文章都是分析的 xml ...

  6. spring security 认证源码跟踪

    spring security 认证源码跟踪 ​ 在跟踪认证源码之前,我们先根据官网说明一下security的内部原理,主要是依据一系列的filter来实现,大家可以根据https://docs.sp ...

  7. Web Api源码(路由注册)

    这篇文章只是我学习Web API框架的输出,学习方法还是输出倒逼输入比较行得通,所以不管写的好不好,坚持下去,肯定有收获.篇幅比较长,仔细思考阅读下来大约需要几分钟. 做.NET开发有好几年时间了,从 ...

  8. Spring AOP高级——源码实现(1)动态代理技术

    在正式进入Spring AOP的源码实现前,我们需要准备一定的基础也就是面向切面编程的核心——动态代理. 动态代理实际上也是一种结构型的设计模式,JDK中已经为我们准备好了这种设计模式,不过这种JDK ...

  9. Spring AOP高级——源码实现(2)Spring AOP中通知器(Advisor)与切面(Aspect)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/Spring%20AOP%E9%A ...

随机推荐

  1. 转:\r,\n,\r\n的区别

    回车.换行的区别   他们间的区别其实是个回车换行的问题 先来段历史 回车”(Carriage Return)和“换行”(Line Feed)这两个概念的来历和区别. 符号        ASCII码 ...

  2. distinct aggregation

    https://docs.google.com/document/d/1zj6OA-K2hi7ah8Fo-xTQB-mVmYfm6LsN2_NHgTCVmJI/edit# https://issues ...

  3. DBeaver利用方式简介

    当攻击者能够进入内网,同时发现某台服务器装有弱口令的数据库时,除了在console中查看数据库信息外, 还可以利用第三方工具进行数据库读取,本例中使用DBeaver进行查看. 1. 下载DBeaver ...

  4. 查准与召回(Precision & Recall)

    Precision & Recall 先看下面这张图来理解了,后面再具体分析.下面用P代表Precision,R代表Recall 通俗的讲,Precision 就是检索出来的条目中(比如网页) ...

  5. Zen Coding)官方文档 一览表

    语法 Child: > nav>ul>li <nav> <ul> <li></li> </ul> </nav> ...

  6. Linux--多网卡的7种Bond模式【转】

    转自:http://www.cnblogs.com/lcword/p/5914089.html 网卡bond是通过把多张网卡绑定为一个逻辑网卡,实现本地网卡的冗余,带宽扩容和负载均衡.在应用部署中是一 ...

  7. 前端复制粘贴clipBoard.js的使用

    <!DOCTYPE html> <html> <head> <title>ClipBoard.js使用:修改HTML</title> < ...

  8. Ubuntu 搜狗输入法崩溃 重启办法

    参考:https://www.findhao.net/res/786 打开终端,执行: pidof fcitx | xargs kill fcitx -r 上面两句意思就是kill fcitx的进程再 ...

  9. maven deploy distributionManagement

    分发构件至远程仓库 mvn install 会将项目生成的构件安装到本地Maven仓库,mvn deploy 用来将项目生成的构件分发到远程Maven仓库.本地Maven仓库的构件只能供当前用户使用, ...

  10. python 字符串格式化转换类型