捋一捋Spring Web的源码思路
Servlet前提
- Java规定了Servlet Container为每一个web app创建一个Servlet Context;而Servlet Context中又包含了诸多Servlet -- 其信息由ServletConfig对象持有,存储于Servlet Context的attribute中。
- Java提供了ServletContainerInitializer,用于发出通知:某个web应用已经处于启动阶段。--其实顾名思义,就是Servlet Container初始化时会调用这个接口的实现方法 onStartup。
- Java提供了五个Listener类 (ServletContextListener、ServletContextAttributeListener、ServletRequestListener、ServletRequestAttributeListener、HttpSessionListener、HttpSessionAttributeListener)来监听Servlet相关的行为。
Spring前提
- Spring Web,其实是创建了WebApplicationContext -- AnnotationConfigWebApplicationContext、XmlWebApplicationContext等。这是Root Application Context。
- 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的源码思路的更多相关文章
- Spring IOC 容器源码分析系列文章导读
1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...
- Spring IOC 容器源码分析
声明!非原创,本文出处 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 S ...
- Spring IOC 容器源码分析(转)
原文地址 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢 ...
- Spring IOC容器源码分析
注:本文转自https://javadoop.com/post/spring-ioc Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容 ...
- 最简 Spring IOC 容器源码分析
前言 BeanDefinition BeanFactory 简介 Web 容器启动过程 bean 的加载 FactoryBean 循环依赖 bean 生命周期 公众号 前言 许多文章都是分析的 xml ...
- spring security 认证源码跟踪
spring security 认证源码跟踪 在跟踪认证源码之前,我们先根据官网说明一下security的内部原理,主要是依据一系列的filter来实现,大家可以根据https://docs.sp ...
- Web Api源码(路由注册)
这篇文章只是我学习Web API框架的输出,学习方法还是输出倒逼输入比较行得通,所以不管写的好不好,坚持下去,肯定有收获.篇幅比较长,仔细思考阅读下来大约需要几分钟. 做.NET开发有好几年时间了,从 ...
- Spring AOP高级——源码实现(1)动态代理技术
在正式进入Spring AOP的源码实现前,我们需要准备一定的基础也就是面向切面编程的核心——动态代理. 动态代理实际上也是一种结构型的设计模式,JDK中已经为我们准备好了这种设计模式,不过这种JDK ...
- Spring AOP高级——源码实现(2)Spring AOP中通知器(Advisor)与切面(Aspect)
本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/Spring%20AOP%E9%A ...
随机推荐
- 在javascript中获取一个对象内属性的个数
var foo = {a1:'1',a2:'2',a3:'3'}; //获得对象所有属性的数组 Object.getOwnPropertyNames(foo); > [ 'a1', 'a2', ...
- django rest_framework入门三-Requests和Responses
这一节,我们介绍rest_framework的Requests和Responses对象,来替代django.http的HttpRequest和HttpResponse对象 1.Requests和Res ...
- django rest_framework入门二-序列化
在前一节中,我们已经粗略地介绍了rest_framework的作用之一序列化,下面我们将详细探究序列化的使用. 1.新建一个app snippets python manage.py startapp ...
- Specular Aliasing与Specular Leaking
最近做高质量实时HDR PBR渲染中碰到了2个关键问题,若干思考如下: 问题1: 极高的动态范围HDR+高级BRDF+相对较低的采样率(比方说不考虑子像素的原始分辨率),在这3项因素的综合作用下,Sp ...
- [DIOCP3-IocpTask说明书]基于IOCP引擎的多线程任务的投递和回调处理单元
[说明] IocpTask是基于Iocp引擎的多线程任务投递和处理单元,可以方便的把任务进行投递到IOCP线程进行统一调度和处理,是模仿QDAC-QWorker的处理方式,支持D7以上的版本. [使用 ...
- 在IIS服务器上屏蔽IP的访问
今天就跟大家分享一下在IIS服务器上如何屏蔽特定IP的访问,希望对大家有所帮助. 第一种方法:通过iis中的ip地址和域名限制. 此方法简单有效,建议使用 点击网站--右键属性--目录安全性--IP地 ...
- 关于electron的跨域问题,有本地的图片的地址,访问不了本地的图片
项目中有上传图片功能,自定义input type=file 改变透明度和超出部分隐藏,把按钮和 点击的图标放在上传文件的按钮上面,然后又碰到到获取input里面的图片的本地的路径, 在electron ...
- 有用的SAP System Administration T-CODE
一,SAP系统管理常用到的事务代码1. SM51 SAP Servers System Monitoring2. SM21 SAP系统日志3. SRZL SAP计算机中心管理系统(CCMS) ...
- LeetCode: Pascal's Triangle II 解题报告
Pascal's Triangle II Total Accepted: 19384 Total Submissions: 63446 My Submissions Question Solution ...
- scala工程导入报错:scalatest_2.10-1.9.1.jar is cross-compiled with an incompatible version of Scala (2.10).
错误原因: The Scala IDE tries to check if binary incompatible Scala libraries have been inadvertently mi ...