Spring MVC 的 HandlerAdapter 是處理器執行的核心適配器,而 ModelFactory 則負責模型數據的初始化與會話屬性同步。本文基於源碼(Spring 4.x/5.x),深入剖析 ModelFactory 的兩大核心職責:模型初始化與會話屬性同步,並解讀關鍵源碼邏輯,幫助開發者透徹理解框架底層運作。
@SessionAttributes 會話屬性、執行 @ModelAttribute 方法、同步方法參數中的會話屬性。SessionStatus 決定清除或存儲會話屬性,必要時綁定 BindingResult。Map<String, ?> attributesInSession = this.sessionAttributesHandler.retrieveAttributes(request); mavContainer.mergeAttributes(attributesInSession);
從會話中取出所有標註 @SessionAttributes 的屬性,合併到 ModelAndViewContainer,供後續處理器使用。
遍歷所有標註 @ModelAttribute 的方法:
value 作為屬性名,若 ModelAndViewContainer 已存在則跳過。InvocableHandlerMethod.invokeForRequest 執行方法獲取返回值。屬性名推導邏輯(Conventions.getVariableNameForReturnType):
String → stringList<Double> → doubleList(集合/數組統一加 List 後綴)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 範圍內的參數,從會話取值同步到模型,若會話無值則拋異常。
if (mavContainer.getSessionStatus().isComplete()) {
this.sessionAttributesHandler.cleanupAttributes(request); // 清除會話屬性
} else {
this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel()); // 存儲模型到會話
}
關鍵結論:SessionStatus.setComplete() 在方法中調用位置無關緊要,因為同步邏輯在處理器執行後統一執行。
若請求未結束(!mavContainer.isRequestHandled()),對模型中符合條件的屬性綁定 BindingResult:
BindingResult 開頭的屬性名(排除已綁定結果)@SessionAttributes 範圍,或ModelFactory:統籌模型生命周期SessionAttributesHandler:會話屬性存取、清理InvocableHandlerMethod:封裝方法調用與參數解析MethodParameter:封裝方法參數元數據HandlerMethodArgumentResolver:參數解析器鏈(責任鏈模式)@ModelAttribute("xxx") value,避免類型推導產生非預期名稱。SessionStatus.setComplete() 僅標記,實際清理在視圖渲染後,適合表單提交完成場景。HandlerMethodArgumentResolver 鏈,可自定義參數解析邏輯(如當前用戶注入)。透過源碼窺探 Spring MVC 核心機制,不僅能解決疑難雜症,更能在架構設計時做出更符合框架哲學的決策。