写在前面
本文的目的是使用300行代码实现Spring MVC 核心原理,读取配置文件,实现自己的ioc容器,实现依赖注入,再根据注解和对应的方法实例化HandlerMapping,更重要的是为之后的源码的阅读提供一个大概的轮廓.
实现的最终结果图 :
首先看这张流程图
总体实现分析
- 首先接收网页请求的是
DispatcherServlet(前端控制器)
,这个前端控制器继承了HttpServlet
, 所以继承了doGet和doPost方法,通过这个分发请求. HandlerMapping(处理器映射器)
,简单来看就是就是一个Map<访问的url,controller层对应的方法>- 这里简单模拟了Spring的处理流程,获取到Handlermapping返回的method之后,直接在DispatcherServlet执行返回.
可以看出我们的SpringMVC框架设计的主要任务就是DispatcherServlet.
DispatcherServlet详细实现分析 :
- 加载配置文件(
web.xml
),通过这个配置文件获得要扫描的路径 - 扫描相关的类,并将其的ClassName获取并保存到
List
中 - 初始化扫描到的类,并将其放到
IOC容器
中 - 进行依赖注入(
DI
) - 初始化
Handlermapping
- 调用阶段,调用
doDispatch()
进行分发
现在开始
详细代码将会单独列出
总体概览
@Override
public void init(ServletConfig config) throws ServletException {
// 初始化阶段
//1.加载配置文件
//ServletConfig通过这个可以获得web.xml中的信息
// 拿到路径值
doLoadConfig(config.getInitParameter("contextConfigLocation"));
//2. 扫描相关的类
doScanner(contextConfig.getProperty("scanPackage"));
// 3. 初始化扫描到的类,并且将其放入IOC容器之中
doInstance();
// 4. 完成依赖注入
doAutowired();
//5. 初始化HandlerMappering
initHandlermapping();
System.out.println("MIMO Spring framework is init .");
}
- 加载配置文件
这一步的主要实现了将application.properties文件转换为输入流对象.并传给一个Properties对象[一种使用键值对保存信息的对象]
private void doLoadConfig(String contextConfigLocation) {
// 读取application.properties文件,并将转换为Properties对象
InputStream fis = null;
fis = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
try {
contextConfig.load(fis);
} catch (IOException e) {
e.printStackTrace();
}
}
- 扫描相关的类
这一步的目的是获得所有的类的className的classNames’List
/**
* 扫描出相关的类
*
* @param scanPackage
*/
private void doScanner(String scanPackage) {
//scanPackage=com.gupaoedu.demo是包路径
//装换为文件路径,将'.'替换为'/'
//这里是replaceall记住要全部进行替换
URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
File classpath = new File(url.getFile());
//遍历classpath下的所有文件
for (File file : classpath.listFiles()
) {
if (file.isDirectory()) {
// 判断是否为一个文件夹,递归,传入父类名+.+文件夹名
doScanner(scanPackage + "." + file.