手动实现springmvc+ioc(思路篇)

小组的一次技术交流中提到手动实现一个mvc框架练练手,对于这个话题我很是的感兴趣。因此写着玩尝试尝试。web

说到mvc框架不得不得说当下最流行的spirngmvc了。下面就来分析下实现思路spring

首先,web项目确定都是基于servlet,咱们先来看看spirng是怎么作的。mvc

随便打开一个spirng的web项目启动来看看app

这段日志咱们能够看出spring在刚启动时正在初始化spirng的上下文。那么初始化上下文又是在作什么呢。咱们一步一步的来分析框架

首先spirng在ContextLoader中开始进行了初始化,那么为何ContextLoader会在应用启动时初始化呢?this

缘由是在web.xml中有这样一段配置url

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

点开里面的源码咱们能够看到这个监听器实现了ServletContextListener接口,实现了这个接口就能在应用启动时自动执行contextInitialized方法,在这里进行spring上下文的初始化spa

public void contextInitialized(ServletContextEvent event) {
   this.contextLoader = createContextLoader();
   if (this.contextLoader == null) {
      this.contextLoader = this;
   }
   this.contextLoader.initWebApplicationContext(event.getServletContext());
}

能够在代码中看到spring上下文初始化时传入了servletContext。在刚开始学servlet时咱们知道servletContext是servlet的上下文,为何要传入这个下面再说日志

读取application.xml配置文件初始化WebApplicationContextxml

而后接着往下读源码发现WebApplicationContext保存在了servletContext,方便咱们随时获取WebApplicationContext,这就是为何要在上图方法中传入servletContext。

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

初始化完WebApplicationContext接下来就是初始化springDispatcherServlet了。springDispatcherServlet是咱们springmvc的核心控制器,它其实就是个sevlet,配置在咱们的web.xml中

<servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-servlet.xml</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>

springDispatcherServlet是咱们spirngmvc的整个核心控件。下面是一个请求的整个过程。具体再也不阐述

在接下来的日志中咱们能够看到来自AbstractUrlHandlerMapping的一堆咱们请求映射的打印。打开这个类看看它到底作了什么。在registerHandler这个方法中咱们能够看到

this.handlerMap.put(urlPath, resolvedHandler);

handlerMap是这个类中定义的一个map,而resolvedHandler则是这个请求的处理类对象。看到这里思路就大概清晰了。springDispatcherServlet接到请求后,根据url找到对应的已经实例化好的处理对象,而后再执行相应的方法。

说到这里大概的思路就已经有了。作个总结。

实现思路(只是个大概)
1.应用启动初始化操做

建立一个contextLoader实现ServletContextListener接口

建立applicationContext上下文,存储在servletContext中
读取xml配置文件获取扫描bean的包路径
经过配置路径获取带有注解的类

经过反射将类实例化,以类名首字母小写或注解上的值为key,实例化的对象为value,将bean存储在上下文中

 

2.初始化dispatchservlet

在web.xml中配置dispatchservlet,拦截全部请求
将全部类中的@requestMapping存储在一个map中,key为url,value为class

将class(controller)反射实例化存储在dispatchservlet的上下文中
从applicationContext获取bean,为filed注入实例

 

3.解析请求

dispatchservlet收到请求

经过threadLocal设置request和response方便在controller中使用。

根据url匹配到对应的class,根据class在dispatchservlet上下文中获取实例。

根据注解value找到对应的方法执行,返回视图。

 

本人道行尚浅,文中若有错误,欢迎指正。

相关文章
相关标签/搜索