成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

SpringMVC之源碼分析--啟動過程

Olivia / 3085人閱讀

摘要:核心類類的繼承關(guān)系前端控制器是規(guī)范中的核心類,實現(xiàn)接口,繼承此類用于處理用戶請求。主要配置中初始化參數(shù)。

Spring MVC 核心類

類的繼承關(guān)系
Spring MVC前端控制器DispatcherServlet-->FrameworkServlet-->HttpServletBean-->HttpServlet

HttpServlet

HttpServlet是Servlet規(guī)范中的核心類,實現(xiàn)Servlet接口,繼承此類用于處理用戶請求。

HttpServletBean

HttpServletBean主要配置servlet中初始化參數(shù)。繼承HttpServlet,并實現(xiàn)無參的init()方法,用于設(shè)置在web.xml中配置的contextConfigLocation屬性,此屬性指定Spring MVC的配置文件地址,默認為WEB-INF/[servlet-name]-servlet.xml,源碼如下:

/**
 * DispatcherServlet第一次加載時調(diào)用init方法
 */
@Override
public final void init() throws ServletException {
    // 省略日志...
    // 獲取在web.xml配置的初始化參數(shù),并將其設(shè)置到DispatcherServlet中
    PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
    if (!pvs.isEmpty()) {
        try {
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
            ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
            bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
            initBeanWrapper(bw);
            bw.setPropertyValues(pvs, true);
        }
        catch (BeansException ex) {
            if (logger.isErrorEnabled()) {
                logger.error("Failed to set bean properties on servlet "" + getServletName() + """, ex);
            }
            throw ex;
        }
    }
    // 調(diào)用子類(FrameworkServlet)進行初始化
    // 模版方法,此方法在HttpServletBean本身是空的,但是因為調(diào)用方法的對象是DispatcherServlet
    // 所以優(yōu)先在DispatcherServlet找,找不到再去父類找,最后在FrameworkServlet找到
    initServletBean();
    if (logger.isDebugEnabled()) {
        logger.debug("Servlet "" + getServletName() + "" configured successfully");
    }
}

總結(jié)HttpServletBean的作用:

獲取web.xml的中配置DispatcherServlet的初始化參數(shù),存放到一個參數(shù)容器ServletConfigPropertyValues中

根據(jù)傳進來的this創(chuàng)建BeanWrapper,本質(zhì)上它就是DispatcherServlet

通過bw.setPropertyValues(pvs, true),把參數(shù)設(shè)置到bw(即DispatcherServlet)里面去

最后調(diào)用子類的initServletBean()

FrameworkServlet

FrameworkServlet主要創(chuàng)建WebApplicationContext上下文,重寫了HttpServletBean的initServletBean()方法。

1、initServletBean

該方法只有兩句關(guān)鍵代碼,其作用一個是調(diào)用initWebApplicationContext()方法初始化WebApplicationContext上下文,另一個是調(diào)用子類方法initFrameworkServlet()方法,源碼如下:

@Override
protected final void initServletBean() throws ServletException {
    getServletContext().log("Initializing Spring FrameworkServlet "" + getServletName() + """);
    // 省略日志...
    long startTime = System.currentTimeMillis();
    try {
        // 初始化WebApplicationContext,并調(diào)用子類(DispatcherServlet)的onRefresh(wac)方法
        this.webApplicationContext = initWebApplicationContext();
        initFrameworkServlet();
    }
    catch (ServletException | RuntimeException ex) {
        this.logger.error("Context initialization failed", ex);
        throw ex;
    }
    if (this.logger.isInfoEnabled()) {
        long elapsedTime = System.currentTimeMillis() - startTime;
        this.logger.info("FrameworkServlet "" + getServletName() + "": initialization completed in " +
                elapsedTime + " ms");
    }
}
2、initWebApplicationContext
protected WebApplicationContext initWebApplicationContext() {
    // 獲取root WebApplicationContext,即web.xml中配置的listener(ContextLoaderListener)
    WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    WebApplicationContext wac = null;
    // 判斷容器是否由編程式傳入(即是否已經(jīng)存在了容器實例),存在的話直接賦值給wac,給springMVC容器設(shè)置父容器
    // 最后調(diào)用刷新函數(shù)configureAndRefreshWebApplicationContext(wac),作用是把Spring MVC配置文件的配置信息加載到容器中去
    if (this.webApplicationContext != null) {
        // context上下文在構(gòu)造是注入
        wac = this.webApplicationContext;
        if (wac instanceof ConfigurableWebApplicationContext) {
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
            if (!cwac.isActive()) {
                // context沒有被refreshed,提供一些諸如設(shè)置父context、設(shè)置應(yīng)用context id等服務(wù)
                if (cwac.getParent() == null) {
                    cwac.setParent(rootContext);
                }
                configureAndRefreshWebApplicationContext(cwac);
            }
        }
    }
    // 在ServletContext中尋找是否有Spring MVC容器,初次運行是沒有的,Spring MVC初始化完畢ServletContext就有了Spring MVC容器
    if (wac == null) {
        wac = findWebApplicationContext();
    }
    // 當wac既沒有沒被編程式注冊到容器中的,也沒在ServletContext找得到,此時就要新建一個Spring MVC容器
    if (wac == null) {
        // 如果沒有WebApplicationContext則創(chuàng)建
        wac = createWebApplicationContext(rootContext);
    }
    // 到這里Spring MVC容器已經(jīng)創(chuàng)建完畢,接著真正調(diào)用DispatcherServlet的初始化方法onRefresh(wac)
    // 此處仍是模板模式的應(yīng)用
    if (!this.refreshEventReceived) {
        onRefresh(wac);
    }
    // 將Spring MVC容器存放到ServletContext中去,方便下次取出來
    if (this.publishContext) {
        // Publish the context as a servlet context attribute.
        String attrName = getServletContextAttributeName();
        getServletContext().setAttribute(attrName, wac);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Published WebApplicationContext of servlet "" + getServletName() +
                    "" as ServletContext attribute with name [" + attrName + "]");
        }
    }
    return wac;
}
3、createWebApplicationContext
protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {
    return createWebApplicationContext((ApplicationContext) parent);
}
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
    Class contextClass = getContextClass();
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Servlet with name "" + getServletName() +
                "" will try to create custom WebApplicationContext context of class "" +
                contextClass.getName() + """ + ", using parent context [" + parent + "]");
    }
    if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
        throw new ApplicationContextException(
                "Fatal initialization error in servlet with name "" + getServletName() +
                "": custom WebApplicationContext class [" + contextClass.getName() +
                "] is not of type ConfigurableWebApplicationContext");
    }
    // 實例化容器
    ConfigurableWebApplicationContext wac =
            (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    // 設(shè)置容器環(huán)境
    wac.setEnvironment(getEnvironment());
    // 設(shè)置父容器
    wac.setParent(parent);
    // 加載Spring MVC的配置信息,如:bean注入、注解、掃描等等
    String configLocation = getContextConfigLocation();
    if (configLocation != null) {
        wac.setConfigLocation(configLocation);
    }
    // 刷新容器,根據(jù)Spring MVC配置文件完成初始化操作
    configureAndRefreshWebApplicationContext(wac);
    return wac;
}

總結(jié)FrameworkServlet的作用:

創(chuàng)建Spring MVC的容器,根據(jù)配置文件實例化里面各種bean,并將之與spring的容器進行關(guān)聯(lián)

把創(chuàng)建出來的Spring MVC容器存放到ServletContext中

通過模板方法模式調(diào)用子類DispatcherServlet的onRefresh()方法

DispatcherServlet

DispatcherServlet是Spring MVC核心,它是J2EE規(guī)范前端控制器的實現(xiàn),負責攔截用戶請求,并解析請求進行轉(zhuǎn)發(fā)。

@Override
protected void onRefresh(ApplicationContext context) {
    initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context); // 文件上傳解析
    initLocaleResolver(context); // 本地解析
    initThemeResolver(context); //主題解析
    initHandlerMappings(context); // URL請求映射
    initHandlerAdapters(context); // 初始化Controller類
    initHandlerExceptionResolvers(context); // 異常解析
    initRequestToViewNameTranslator(context); 
    initViewResolvers(context); // 視圖解析
    initFlashMapManager(context);
}
總結(jié)

容器啟動時,加載web.xml部署描述文件,掃描到并找到DispatcherServlet核心控制器

調(diào)用HttpServletBean的init()方法,把DispatcherServlet初始化參數(shù)設(shè)置到DispatcherServlet中,并調(diào)用子類FrameworkServlet的initServletBean()方法

FrameworkServlet的initServletBean()創(chuàng)建Spring MVC容器并初始化,并且和Spring父容器進行關(guān)聯(lián),使得Spring MVC容器能訪問Spring容器中定義的bean,之后調(diào)用子類DispatcherServlet的onRefresh()方法

DispatcherServlet的onRefresh(ApplicationContext context)對DispatcherServlet的策略組件進行初始化

最后創(chuàng)建了qq群方便大家交流,可掃描加入,同時也可加我qq:276420284,共同學習、共同進步,謝謝!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/69261.html

相關(guān)文章

  • SpringMVC源碼分析--HandlerMapping(一)

    摘要:接口接口作用是將請求映射到處理程序,以及預處理和處理后的攔截器列表,映射是基于一些標準的,其中的細節(jié)因不同的實現(xiàn)而不相同。該參數(shù)是類型,作用是檢查所有的映射解析器或使用或為的,默認為,即從上下文中檢查所有的。 概述 在Spring MVC啟動章節(jié)https://segmentfault.com/a/1190000014674239,介紹到了DispatcherServlet的onRef...

    ralap 評論0 收藏0
  • SpringMVC源碼分析--HandlerAdapter(二)

    摘要:概述本章我們主要分析處理組件的處理流程以及其接口源碼。概括來說,使用組件分為兩步,首先是注冊組件,其次是處理用戶請求,以下針對這兩個過程進行詳細的分析。本系列文章是基于。接下來的幾章將分析提供的適配策略,希望本節(jié)對大家能有幫助,謝謝。 概述 本章我們主要分析Spring處理HandlerAdapter組件的處理流程以及其接口源碼。概括來說,Spring使用HandlerAdapter組...

    Eastboat 評論0 收藏0
  • SpringMVC源碼分析--HandlerMapping(三)

    摘要:與類圖對比,類繼承自抽象類,其又繼承自抽象類,再往上繼承關(guān)系與一致。創(chuàng)建初始化上一章我們分析了的創(chuàng)建初始化過程,的創(chuàng)建初始化過程與一樣,方法的入口在抽象類中的方法。至此,代碼編寫完畢。 概述 本節(jié)我們繼續(xù)分析HandlerMapping另一個實現(xiàn)類BeanNameUrlHandlerMapping,從類的名字可知,該類會根據(jù)請求的url與spring容器中定義的bean的name屬性值...

    fsmStudy 評論0 收藏0
  • SpringMVC源碼分析--LocaleResolver和ThemeResolver應(yīng)用

    摘要:需求根據(jù)客戶端環(huán)境,界面顯示不同的國旗圖案。選擇的技術(shù)方案可利用提供的國際化和主題定制來解決。注意此時返回的中沒有國際化及主題相關(guān)的信息。修改請求參數(shù)的值為荷蘭,即后再發(fā)起請求,結(jié)果如下與預期一致,測試通過。 概述 以上分析了Spring MVC的LocaleResolver和ThemeResolver兩個策略解析器,在實際項目中很少使用,尤其是ThemeResolver,花精力去分析...

    qpal 評論0 收藏0
  • SpringMVC源碼分析--HandlerMapping(二)

    摘要:由于抽象類重寫了父類的方法,所以此時會調(diào)用的方法,在該方法中通過調(diào)用父類的方法,該方法通過模板方法模式最終調(diào)到類的方法。分析該類間接實現(xiàn)了接口,直接實現(xiàn)該接口的是抽象類,映射與請求。 概述 在前一章https://segmentfault.com/a/1190000014901736的基礎(chǔ)上繼續(xù)分析,主要完成SimpleUrlHandlerMapping類的原理。 本系列文章是基于Sp...

    Imfan 評論0 收藏0

發(fā)表評論

0條評論

Olivia

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<