手動實現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找到對應的方法執行,返回視圖。

 

本人道行尚淺,文中若有錯誤,歡迎指正。

相關文章
相關標籤/搜索