国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

Olivia / 3052人閱讀

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

Spring MVC 核心類

類的繼承關系
Spring MVC前端控制器DispatcherServlet-->FrameworkServlet-->HttpServletBean-->HttpServlet

HttpServlet

HttpServlet是Servlet規范中的核心類,實現Servlet接口,繼承此類用于處理用戶請求。

HttpServletBean

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

/**
 * DispatcherServlet第一次加載時調用init方法
 */
@Override
public final void init() throws ServletException {
    // 省略日志...
    // 獲取在web.xml配置的初始化參數,并將其設置到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;
        }
    }
    // 調用子類(FrameworkServlet)進行初始化
    // 模版方法,此方法在HttpServletBean本身是空的,但是因為調用方法的對象是DispatcherServlet
    // 所以優先在DispatcherServlet找,找不到再去父類找,最后在FrameworkServlet找到
    initServletBean();
    if (logger.isDebugEnabled()) {
        logger.debug("Servlet "" + getServletName() + "" configured successfully");
    }
}

總結HttpServletBean的作用:

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

根據傳進來的this創建BeanWrapper,本質上它就是DispatcherServlet

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

最后調用子類的initServletBean()

FrameworkServlet

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

1、initServletBean

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

@Override
protected final void initServletBean() throws ServletException {
    getServletContext().log("Initializing Spring FrameworkServlet "" + getServletName() + """);
    // 省略日志...
    long startTime = System.currentTimeMillis();
    try {
        // 初始化WebApplicationContext,并調用子類(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;
    // 判斷容器是否由編程式傳入(即是否已經存在了容器實例),存在的話直接賦值給wac,給springMVC容器設置父容器
    // 最后調用刷新函數configureAndRefreshWebApplicationContext(wac),作用是把Spring MVC配置文件的配置信息加載到容器中去
    if (this.webApplicationContext != null) {
        // context上下文在構造是注入
        wac = this.webApplicationContext;
        if (wac instanceof ConfigurableWebApplicationContext) {
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
            if (!cwac.isActive()) {
                // context沒有被refreshed,提供一些諸如設置父context、設置應用context id等服務
                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則創建
        wac = createWebApplicationContext(rootContext);
    }
    // 到這里Spring MVC容器已經創建完畢,接著真正調用DispatcherServlet的初始化方法onRefresh(wac)
    // 此處仍是模板模式的應用
    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);
    // 設置容器環境
    wac.setEnvironment(getEnvironment());
    // 設置父容器
    wac.setParent(parent);
    // 加載Spring MVC的配置信息,如:bean注入、注解、掃描等等
    String configLocation = getContextConfigLocation();
    if (configLocation != null) {
        wac.setConfigLocation(configLocation);
    }
    // 刷新容器,根據Spring MVC配置文件完成初始化操作
    configureAndRefreshWebApplicationContext(wac);
    return wac;
}

總結FrameworkServlet的作用:

創建Spring MVC的容器,根據配置文件實例化里面各種bean,并將之與spring的容器進行關聯

把創建出來的Spring MVC容器存放到ServletContext中

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

DispatcherServlet

DispatcherServlet是Spring MVC核心,它是J2EE規范前端控制器的實現,負責攔截用戶請求,并解析請求進行轉發。

@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);
}
總結

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

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

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

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69261.html

相關文章

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

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

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

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

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

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

    fsmStudy 評論0 收藏0
  • SpringMVC源碼分析--LocaleResolver和ThemeResolver應用

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

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

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

    Imfan 評論0 收藏0

發表評論

0條評論

Olivia

|高級講師

TA的文章

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