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

Jetty 載入 Spring 容器源碼深度解析:Listener 與 Servlet 初始化順序的底層邏輯

     編輯:Java 綜合教學

核心疑問

  1. web.xml 中 contextConfigLocation、ContextLoaderListener、DispatcherServlet 宣告順序是否影響啟動?
  2. 為何 applicationContext.xml (父容器) 總先於 spring-mvc-servlet.xml (子容器) 初始化?
  3. 兩個容器關係如何?能否移除父容器?

關鍵發現:Listener 必先於 Servlet 執行

Jetty 原始碼鏈路證明:

Server.start()
  → AbstractLifeCycle.start()
  → WebAppContext.doStart()
    → WebAppContext.startContext()
      → ServletContextHandler.startContext()  // 關鍵分水嶺
        → ContextHandler.startContext()       // 1. 初始化所有 Listener (含 ContextLoaderListener)
        → ServletHolder.initialize()          // 2. 初始化 Servlet (含 DispatcherServlet)

Jetty 初始化調用鏈

ContextLoaderListener 初始化父容器流程

  1. contextInitialized(ServletContextEvent) 入口
  2. ContextLoader.initWebApplicationContext()
  3. 判斷 WebApplicationContext.ROOT 為空 → 建立 XmlWebApplicationContext
  4. configAndRefresh() → 讀取 contextConfigLocation → AbstractApplicationContext.refresh() 完成 Bean 定義載入、實例化、注入

DispatcherServlet 初始化子容器流程

  1. FrameworkServlet.initServletBean() 入口
  2. initWebApplicationContext() 建立 XmlWebApplicationContext
  3. 關鍵:子容器設定父容器為 Parent → wac.setParent(rootContext)
  4. refresh() 掃描 spring-mvc-servlet.xml (僅掃描 @Controller 等 Web 組件)

容器關係最佳實踐

<!-- applicationContext.xml: 業務層、數據層 -->
<context:component-scan base-package="com.example">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!-- spring-mvc-servlet.xml: 僅掃描 Web 層 -->
<context:component-scan base-package="com.example.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/" />
    <property name="suffix" value=".jsp" />
</bean>

為何不建議移除父容器?

  • 服務層、數據層 Bean 被多 Servlet 共享 (如 REST API + 後台管理)
  • 事務管理、連接池、緩存等基礎設施單例化
  • 父子容器隔離職責,避免 Web 層 Bean 污染業務層

總結

Jetty 遵循 Servlet 規範:Listener 初始化 → Filter 初始化 → Servlet 初始化。此順序由容器生命週期模板方法強制保證,與 web.xml 宣告順序無關。父子容器雙層架構是 Spring MVC 設計的基石,正確配置掃描範圍是避免 Bean 重複、循環依賴的關鍵。

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