首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring MVC 源碼深度解析:HandlerAdapter 與 ModelFactory 核心機制

     編輯:Java 綜合教學

Spring MVC 源碼深度解析:HandlerAdapter 與 ModelFactory 核心機制

Spring MVC 的 HandlerAdapter 是處理器執行的核心適配器,而 ModelFactory 則負責模型數據的初始化與會話屬性同步。本文基於源碼(Spring 4.x/5.x),深入剖析 ModelFactory 的兩大核心職責:模型初始化與會話屬性同步,並解讀關鍵源碼邏輯,幫助開發者透徹理解框架底層運作。

一、ModelFactory 核心職責概覽

  1. 初始化模型:合併 @SessionAttributes 會話屬性、執行 @ModelAttribute 方法、同步方法參數中的會話屬性。
  2. 處理器執行後同步模型到會話:根據 SessionStatus 決定清除或存儲會話屬性,必要時綁定 BindingResult。

二、模型初始化三階段詳解

1.1 合併 @SessionAttributes 定義的會話屬性

Map<String, ?> attributesInSession = this.sessionAttributesHandler.retrieveAttributes(request);
mavContainer.mergeAttributes(attributesInSession);

從會話中取出所有標註 @SessionAttributes 的屬性,合併到 ModelAndViewContainer,供後續處理器使用。

1.2 執行 @ModelAttribute 方法並同步結果到模型

遍歷所有標註 @ModelAttribute 的方法:

  • 獲取註解 value 作為屬性名,若 ModelAndViewContainer 已存在則跳過。
  • 委託 InvocableHandlerMethod.invokeForRequest 執行方法獲取返回值。
  • 非 void 方法需將返回值同步到容器,屬性名生成規則:註解 value > 返回值類型推導。

屬性名推導邏輯(Conventions.getVariableNameForReturnType):

  • String → string
  • List<Double> → doubleList(集合/數組統一加 List 後綴)
  • 泛型類型會解析元素類型再複數化

1.3 同步 @ModelAttribute 方法參數中的會話屬性

for (String name : findSessionAttributeArguments(handlerMethod)) {
    if (!mavContainer.containsAttribute(name)) {
        Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
        if (value == null) throw new HttpSessionRequiredException(...);
        mavContainer.addAttribute(name, value);
    }
}

掃描處理器方法參數,找出同時標註 @ModelAttribute 且在 @SessionAttributes 範圍內的參數,從會話取值同步到模型,若會話無值則拋異常。

三、處理器執行後:會話屬性同步與 BindingResult 綁定

2.1 根據 SessionStatus 決定清除或存儲

if (mavContainer.getSessionStatus().isComplete()) {
    this.sessionAttributesHandler.cleanupAttributes(request); // 清除會話屬性
} else {
    this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel()); // 存儲模型到會話
}

關鍵結論:SessionStatus.setComplete() 在方法中調用位置無關緊要,因為同步邏輯在處理器執行後統一執行。

2.2 BindingResult 綁定條件

若請求未結束(!mavContainer.isRequestHandled()),對模型中符合條件的屬性綁定 BindingResult:

  • 非 BindingResult 開頭的屬性名(排除已綁定結果)
  • 屬於 @SessionAttributes 範圍,或
  • 非 null、非數組/集合/Map/簡單類型的複雜對象

四、核心類協作關係圖解

  • ModelFactory:統籌模型生命周期
  • SessionAttributesHandler:會話屬性存取、清理
  • InvocableHandlerMethod:封裝方法調用與參數解析
  • MethodParameter:封裝方法參數元數據
  • HandlerMethodArgumentResolver:參數解析器鏈(責任鏈模式)

五、實戰啟示

  1. @ModelAttribute 方法優先執行:每次請求前先於處理器方法執行,慎用耗時操作。
  2. 屬性名衝突避免:顯式指定 @ModelAttribute("xxx") value,避免類型推導產生非預期名稱。
  3. 會話屬性生命周期:SessionStatus.setComplete() 僅標記,實際清理在視圖渲染後,適合表單提交完成場景。
  4. 參數解析器擴展:理解 HandlerMethodArgumentResolver 鏈,可自定義參數解析邏輯(如當前用戶注入)。

透過源碼窺探 Spring MVC 核心機制,不僅能解決疑難雜症,更能在架構設計時做出更符合框架哲學的決策。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved