捋一捋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 ...
随机推荐
- kernel dump Analysis
https://social.msdn.microsoft.com/Forums/vstudio/en-US/0c418482-7edd-4c91-b7f4-6005d550244a/got-the- ...
- angular-resource版本差异问题
在 AngularJS v1.3.0-beta.14 这个版本里,使用query方法,如果传递进来的数据不是数组,会报错. 在 AngularJS v1.2.18 这个版本里,使用query方法,如果 ...
- Web服务器缓存
前面提到的一些缓存技术都是有我们的动态才程序控制的,现在的web服务器功能越来越强大,常用的web服务器软件也都内置了缓存功能,下面我们就简单的说下服务器端缓存的应用. 首先,我们先来介绍一下URL映 ...
- Makefile常用万能模板(包括静态链接库、动态链接库、可执行文件)
本文把makefile 分成了三份:生成可执行文件的makefile,生成静态链接库的makefile,生成动态链接库的makefile. 这些makefile都很简单,一般都是一看就会用,用法也很容 ...
- curl传输文件实例
curl -H "Authorization:Bearer 5d719398-4230-44c7-b88b-f280b6a8d070" -H "Accept: appli ...
- Oracle sql%rowcount 返回影响行数;sql server @@RowCount返回影响行数
sql server中,返回影响行数是:If @@RowCount<1 Oracle中,返回影响行数是:If sql%rowcount<1 例: sqlserver: create pro ...
- 如何在Windows环境下模拟丢包
[本文出自天外归云的博客园] Q&A Question: How to simulate packet loss on Windows? Answer: Clumsy, an utility ...
- 问题-DelphiXE10.1 FireDAC联接oracle数据库方法
问题现象:安装oracle后,安装Delphi10.1,放FDConnection1时,选择"Ora"驱动时,提示如下: [FireDAC][Phys][Ora]-315. Can ...
- CTF中常见Web源码泄露总结
目录00x1 .ng源码泄露 00x2 git源码泄露 00x3 .DS_Store文件泄漏 00x4 网站备份压缩文件 00x5 SVN导致文件泄露 00x6 WEB-INF/web.xml泄露 ...
- WebAPI 消息处理器
由上图可以看出消息处理器的使用场合和使用方法. 使用场合: HttpServer 得到请求时. public static class WebApiConfig { public static voi ...