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. KVM虚拟机安装报错 KVM is not available

    在linux系统上使用kvm安装系统时,如果你的cpu不支持虚拟化技术那么可能会报以下错误: Warning:KVM is not available. This may mean the KVM p ...

  2. 【Acm】算法之美—Jugs

    题目概述:Jugs In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were confronted wi ...

  3. Android NDK之二:创建NativeActivity

    转:http://blog.csdn.net/xiruanliuwei/article/details/7560914 Android NDK为我们提供了两种方式来实现我们的native activi ...

  4. Lintcode: Minimum Subarray 解题报告

    Minimum Subarray 原题链接: http://lintcode.com/zh-cn/problem/minimum-subarray/# Given an array of intege ...

  5. 【机器学习】DBSCAN Algorithms基于密度的聚类算法

    一.算法思想: DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法.与划分和层 ...

  6. java多线程18: ThreadLocal的作用

    从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal. ...

  7. Python3求英文文档中每个单词出现的次数并排序

    [本文出自天外归云的博客园] 题目要求: 1.统计英文文档中每个单词出现的次数. 2.统计结果先按次数降序排序,再按单词首字母降序排序. 3.需要考虑大文件的读取. 我的解法如下: import ch ...

  8. Ubuntu 16.04 搭建KVM环境

      在Ubuntu 16.04下搭建KVM环境过程记录. 1 查看CPU是否支持KVM egrep "(svm|vmx)" /proc/cpuinfo 有结果输出,如下图: 2 安 ...

  9. ILOG JRules 和 WebSphere Process Server 集成概述

    ILOG JRules 和 WebSphere Process Server 集成概述 简介 业务流程管理(Business Process Management,BPM)和业务规则管理系统(Busi ...

  10. 从Unauthorized 401错误学习Spring Boot的Actuator

    之前用Spring Boot都是别人搭好的框架,然后自己在里面写就行了.对原理.细节上都怎么涉及,毕竟需求都做不完.但是昨天一个访问RESTful接口的401问题搞了我2个小时.网上找的很多用: ma ...