spring mvc 启动过程及源码分析
由于公司开源框架选用的spring+spring mvc + mybatis。使用这些框架,网上都有现成的案例;需要那些配置文件、每种类型的配置文件的节点该如何书写等等。如果只是需要项目能够跑起来,只要按照网上的例子依葫芦画瓢就可,项目也能够运行起来。但是对于有长远目标的人来说,一件事应当知其然更要知其所以然。所以结合网上的其他人阅读spring源码的经验(网上很多人的阅读经验是按照spring分出的那些模块[七大模块:core,context,dao,orm,web,aop,web mvc]来解读)。但是本篇想换个角度来。就根据自己平时项目运行的那个角度来解读。大概得到了解下为什么在配置文件中加上对应的扫描路径,spring容器就能够加载这个路径下面的所有相关的类;我们定义的类是在哪个步骤实例化的、类与类之间的是怎么装配的等等。
对于web项目,我们知道tomcat容器首先加载的文件就是项目中配置的web.xml。在这个文件里面,配置者项目启动需要的所有资源。因此,调试的第一步就是读懂web.xml。无论是ssh,ssm类型的项目来说,web.xml的配置都一样;需要配置spring的ContextLoaderListener监听器;如下:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
需要配置一个servlet,这样,将所有的请求都拦截交给spring来处理
<servlet>
<servlet-name>springServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
web.xml的加载顺序:context-param -> listener -> filter -> servlet
对于context-param来说,它就像是Java里的静态变量,在容器一启动的时候就将对应的值加载进容器里边了。由以下配置文件可看出
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
那就先从contextLoadListener入手,首先查看它的类图:它的作用是在容器初始化的时候做些操作和在容器销毁,程序销毁的时候做资源回收的事情。所以终点关注下 ContextLoaderListener的 contextInitialized方法(调用父类)
初始化context,将context设置为XmlApplicationContext来处理容器资源的初始化。
获取contextParam中的配置信息。继而调用ConfigurableWebApplicationContext.redresh()。在refresh方法里面会实例声明的bean。
实例化bean:
ConfigurableWebApplicationContext.redresh()。多态的呈现,父类引用指向子类对象(AbstractApplicationContext)。
XmlApplicationContext对配置文件的解析。首先会获取web.xml配置文件路径,然后将这些路径循环给到xmlBeanDefinition来解析。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = this.getConfigLocations();
if(configLocations != null) {
String[] var3 = configLocations;
int var4 = configLocations.length;
for(int var5 = 0; var5 < var4; ++var5) {
String configLocation = var3[var5];
reader.loadBeanDefinitions(configLocation);
}
}
转换为对应时序图如下:
最后,所有的解析xml工作都交给了XMLBeanDefinitionReader。
Document doc = this.doLoadDocument(inputSource, resource);
return this.registerBeanDefinitions(doc, resource);
遇到对应的标签做相应的操作。xml中的namespace对应的handler如下:
public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
this(classLoader, "META-INF/spring.handlers");
}
实际读取的文件是spring内置的配置。详细如下(每个namespace对应的handler):
http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
以spring.xml中context标签为例。当程序解析到这个标签的时候,会找到标签所映射的具体handler。每个标签解析完找到对应的handler后都会调用init(),init方法体如下:每一个标签值对应的parser,解析类是不同的。
public void init() {
this.registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
this.registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
this.registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
this.registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
this.registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
this.registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
每一个标签值对应的parser,解析类是不同的。已最常见的自动扫面包路径来说,component-scan。
这样,配置文件中的bean就被实例化了。
以上就是针对spring mvc框架启动过程中所做的那些事。做的简答的概述。方法间调用关系没找到好的方式表现出来,所以就选了时序图这种方式来体现。
spring mvc 启动过程及源码分析的更多相关文章
- Netty服务端启动过程相关源码分析
1.Netty 是怎么创建服务端Channel的呢? 我们在使用ServerBootstrap.bind(端口)方法时,最终调用其父类AbstractBootstrap中的doBind方法,相关源码如 ...
- spring mvc之请求过程源码分析
简介 上一篇,我们分析了spring mvc启动过程的源码,这一节,来一起分析下在用户请求controller的过程中,spring mvc做了什么事? 一.准备 我写这么一个controller p ...
- Spring Boot 揭秘与实战 源码分析 - 工作原理剖析
文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...
- Spring MVC启动过程(1):ContextLoaderListener初始化
此文来自https://my.oschina.net/pkpk1234/blog/61971 (写的特别好)故引来借鉴 Spring MVC启动过程 以Tomcat为例,想在Web容器中使用Spirn ...
- Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机
文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...
- Spring Environment(二)源码分析
Spring Environment(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Envi ...
- Flink的Job启动TaskManager端(源码分析)
前面说到了 Flink的JobManager启动(源码分析) 启动了TaskManager 然后 Flink的Job启动JobManager端(源码分析) 说到JobManager会将转化得到 ...
- Spring Boot JDBC:加载DataSource过程的源码分析及yml中DataSource的配置
装载至:https://www.cnblogs.com/storml/p/8611388.html Spring Boot实现了自动加载DataSource及相关配置.当然,使用时加上@EnableA ...
- Spring MVC工作原理及源码解析(二)DispatcherServlet实现原理及源码解析
1.DispatcherServlet 处理流程 从上一篇文章中Spring MVC原理图中我们可以看出:DispatcherServlet 在 Spring MVC框架 中处于核心位置,它负责协调和 ...
随机推荐
- atx-agent minicap、minitouch源码分析
项目描述: 因为公司需要,特别研究了一下openatx系列手机群控源码 源码地址: https://github.com/openatx 该项目主要以go语言来编写服务端.集成 OpenSTF中核心组 ...
- python从入门到实践-8章函数
#!/user/bin/env python# -*- coding:utf-8 -*- # 给形参指定默认值时,等号两边不要有空格 def function_name("parameter ...
- C++或C#调用外部exe的分析
假如有个外部程序名为A.exe,放在目录E:\temp\下,然后我们用C++或者C#写一个程序调用这个A.exe的话(假设这个调用者所在的路径在D:\invoke),通常会采用下面的代码: // C# ...
- 分享13道上海尚学堂拿回来的Java面试真题,这些都是Java核心常见问题,想拿OFFER必看!
上海尚学堂Java培训学员参加面试带回来的真题,分享出来与大家,希望大家能认真地看看做一遍.后面有详细题解答案,对照下,看看自己做得怎么样,把这些面试遇到的真题全部掌握,做好面试笔试前的准备. 一.1 ...
- [Swift]LeetCode322. 零钱兑换 | Coin Change
You are given coins of different denominations and a total amount of money amount. Write a function ...
- 【阿里面试系列】Java线程的应用及挑战
文章简介 上一篇文章[「阿里面试系列」搞懂并发编程,轻松应对80%的面试场景]我们了解了进程和线程的发展历史.线程的生命周期.线程的优势和使用场景,这一篇,我们从Java层面更进一步了解线程的使用.关 ...
- 【Impala篇】---Hue从初始到安装应用
一.前述 Cloudera公司推出,提供对HDFS.Hbase数据的高性能.低延迟的交互式SQL查询功能.基于Hive使用内存计算,兼顾数据仓库.具有实时.批处理.多并发等优点 是CDH平台首选的PB ...
- WebSocket(3)---实现一对一聊天功能
实现一对一聊天功能 功能介绍:实现A和B单独聊天功能,即A发消息给B只能B接收,同样B向A发消息只能A接收. 本篇博客是在上一遍基础上搭建,上一篇博客地址:[WebSocket]---实现游戏公告功能 ...
- .NET Core中的性能测试工具BenchmarkDotnet
背景介绍 之前一篇博客中,我们讲解.NET Core中的CSV解析库,在文章的最后,作者使用了性能基准测试工具BenchmarkDotNet测试了2个不同CSV解析库的性能,本篇我们来详细介绍一下Be ...
- Android--SoundPool
前言 在Android中播放音频文件经常会用到MediaPlayer,但是MediaPlayer存在一些不足的地方,如:资源占用量较高.加载延迟时间较长.不支持多个音频同时播放等.这些缺点决定了Med ...